我正在从未设置的SQL Server数据库中获取一些数据。这是一个生产环境,所以我不想改变太多。
我正在获取数据并使用获取的数据填充各种类型的对象。某些对象只需要一个表中的数据;其他人需要联接才能获取所有必要的数据。
有很多表有一个时间戳列time
,通常存储在datetime
或datetimeoffset
列类型中。这通常是查询应按列排序的依据。但是,有几个表,其中时间戳存储在ndate
列(仅存储日期(和ntime
列(仅存储时间(中。将这些值相加将产生正确的时间戳。
因此,要使此表的行为与其他表类似,并使列映射到对象属性,最简单和最明显的做法很简单:
SELECT *, (ndate + ntime) AS time
FROM tableA
WHERE x = z
ORDER BY time DESC
这工作得很好。但是,如果对象是需要来自多个表的数据的对象之一,则会弹出一个明显的问题。如果tableA
联接tableB
而后者有一个time
列,那么我无法弄清楚如何按别名time
列对查询进行排序:
SELECT *, (ndate + ntime) AS time
FROM tableA
LEFT JOIN tableB
WHERE x = z
ORDER BY time DESC
– 产生一个通知,表明time
是模棱两可的,当然是这样。
SELECT *, (ndate + ntime) AS time
FROM tableA
LEFT JOIN tableB
WHERE x = z
ORDER BY tableA.time DESC
– 产生一个通知,指出tableA.time
是无效列,当然是这样,因为它不是表中实际存在的列。
当然,有各种或多或少繁琐的方法可以解决这个问题。我设法想出的最简单方法是将tableA
(带有别名列("包装"在子查询中,然后子查询将具有可引用的别名,使列明确:
SELECT *
FROM
(SELECT *, (ndate + ntime) AS time
FROM tableA) AS subTable
LEFT JOIN tableB
WHERE x = z
ORDER BY subTable.time DESC
这就是我所说的相当简单的,但它仍然使查询的可读性比原始查询差得多,而原始查询非常简单。
显然,这不是你所说的严重问题,但它仍然让我怀疑是否有一种不那么"破坏性"的方式来实现相同的最终目标。
是否有一种侵入性更小的方法,它保留了原始查询的更多简单性?
您可以使用"交叉应用"或简单地使用原始表达式进行排序依据。 即:
SELECT *, (ndate + ntime) AS time
FROM tableA
LEFT JOIN tableB
WHERE x = z
ORDER BY (ndate + ntime) DESC;
注意:这里存在尝试使用 * 在结果集中创建多个"时间"列的问题。您可能会列出您想要的列(无论如何这是推荐的方式(。或者将您的"时间"命名为其他名称。
是的-ORDER BY 1
将按您选择的第一列排序,无论它是什么。当然,如果您更改第一列的顺序,则更改顺序
SELECT (tableA.ndate + tableA.ntime) AS time, tableA.*, tableB.*
FROM tableA LEFT JOIN tableB WHERE x = z ORDER BY 1 DESC
由于您不知道*
有多少列,因此您首先按列排序。
您可能希望添加为您创建time
的计算列。
编辑
我不确定下面的评论中关于外部连接的混淆是什么。我在查询中添加了一些详细信息。