明确引用不明确的列别名的最不麻烦的方法?

Least cumbersome way to unambiguously reference an ambiguous column alias?

我正在从我未设置的 SQL 服务器数据库中获取一些数据。这是一个生产环境,所以我不想做太多改变。

我正在获取数据并使用获取的数据填充各种类型的对象。有些对象只需要一个 table 的数据;其他人需要加入才能获得所有必要的数据。

有很多table有时间戳列time,通常存储在datetimedatetimeoffset列类型中。这通常是列查询应该排序的依据。不过,有几个 table 时间戳存储在 ndate 列(仅存储日期)和 ntime 列(仅存储时间)中。将这些值相加会产生正确的时间戳。

然后,要使这个 table 的行为与其他的一样并让列映射到对象属性,最简单和最明显的事情就是:

SELECT *, (ndate + ntime) AS time 
FROM tableA 
WHERE x = z 
ORDER BY time DESC

这很好用。但是,如果该对象是需要来自多个 table 的数据的对象之一,就会出现一个明显的问题。如果 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 是无效列,这当然是无效列,因为它不是 table 中实际存在的列。

当然有各种或多或少麻烦的方法来解决这个问题。我设法想出的最简单的方法是在子查询中“包装”tableA(使用别名列),然后它将有一个可引用的别名,使列明确:

SELECT * 
FROM 
    (SELECT *, (ndate + ntime) AS time 
     FROM tableA) AS subTable 
LEFT JOIN tableB 
WHERE x = z 
ORDER BY subTable.time DESC

这就是我所说的相当简单,但它仍然使查询的可读性比原来的查询要差很多,这是非常简单的。

很明显,这不是你所说的严重问题,但它仍然让我想知道是否有一种“破坏性”较小的方法来实现相同的最终目标。

有没有一种侵入性更小的方法,它保留了原始查询的更多简单性?

是 - ORDER BY 1 将按 select 的第一列排序,无论它是什么。当然,如果您更改第一列的顺序,则更改

SELECT (tableA.ndate + tableA.ntime) AS time, tableA.*, tableB.*
FROM tableA LEFT JOIN tableB WHERE x = z ORDER BY 1 DESC

由于您不知道 * 中有多少列,所以您先按列排序。

您可能想要添加一个计算列,为您创建 time

编辑

我不确定下面的评论中关于外连接的混淆是什么。我在查询中添加了一些详细信息。

您可以使用"cross apply"或简单地使用原始表达式进行排序。即:

SELECT *, (ndate + ntime) AS time 
FROM tableA 
LEFT JOIN tableB 
WHERE x = z 
ORDER BY (ndate + ntime) DESC;

注意:这里存在尝试使用 * 在结果集中创建多个 "time" 列的问题。可能您会改为列出您想要的列(无论如何这是推荐的方式)。或者将您的 "time" 命名为其他名称。