我正在从我未设置的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
这就是我所说的相当简单,但是它仍然使查询的可读性比原始查询低得多,这非常简单。
很明显,这不是您要解决的严重问题,但这仍然让我感到疑惑,是否可能没有“破坏性”的方法来实现相同的最终目标。
是否有更不那么麻烦的方式来执行此操作,从而保留了原始查询的更多简单性?
答案 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;
注意:这里存在尝试使用*在结果集中创建多个“时间”列的问题。可能您会列出您想要的列(无论如何建议这样做)。或将您的“时间”命名为其他名称。