最少麻烦的方式来明确引用歧义的列别名?

时间:2018-08-22 23:34:28

标签: sql-server alias

我正在从我未设置的SQL Server数据库中获取一些数据。这是一个生产环境,所以我不想比绝对必要做更多的更改。

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

很多表都有一个时间戳列time,通常以datetimedatetimeoffset列类型存储。通常这是列查询的排序依据。但是,有几个表将时间戳存储在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

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

很明显,这不是您要解决的严重问题,但这仍然让我感到疑惑,是否可能没有“破坏性”的方法来实现相同的最终目标。

是否有更不那么麻烦的方式来执行此操作,从而保留了原始查询的更多简单性?

2 个答案:

答案 0 :(得分:1)

是-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

编辑

我不确定下面的评论中关于外部联接的困惑是什么。我已经在查询中添加了一些细节。

答案 1 :(得分:1)

您可以使用“交叉应用”,也可以仅使用原始表达式进行排序。即:

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

注意:这里存在尝试使用*在结果集中创建多个“时间”列的问题。可能您会列出您想要的列(无论如何建议这样做)。或将您的“时间”命名为其他名称。