我在MSSQL表(TableB)中有数据,其中[dbo] .tableB.myColumn在特定日期之后更改格式...
我正在简单地加入那张桌子..
Select [dbo].tableB.theColumnINeed from [dbo].tableA
left outer join [dbo].tableB on [dbo].tableA.myColumn = [dbo].tableB.myColumn
但是,我需要使用不同的格式加入,基于表A中的日期列([dbo] .tableA.myDateColumn)。
像...一样的东西。
Select [dbo].tableB.theColumnINeed from [dbo].tableA
left outer join [dbo].tableB on [dbo].tableA.myColumn =
IF [dbo].tableA.myDateColumn > '1/1/2009'
BEGIN
FormatColumnOneWay([dbo].tableB.myColumn)
END
ELSE
BEGIN
FormatColumnAnotherWay([dbo].tableB.myColumn)
END
我想知道是否有办法做到这一点..或者更好的方式我不想考虑这个......
答案 0 :(得分:8)
SELECT [dbo].tableB.theColumnINeed
FROM [dbo].tableA
LEFT OUTER JOIN [dbo].tableB
ON [dbo].tableA.myColumn =
CASE
WHEN [dbo].tableA.myDateColumn <= '1/1/2009' THEN FormatColumnOneWay([dbo].tableB.myColumn)
ELSE FormatColumnAnotherWay([dbo].tableB.myColumn)
END
答案 1 :(得分:5)
您可以考虑使用UNION
而不是在JOIN中使用CASE语句(这将阻止使用索引进行查询)SELECT [dbo].tableB.theColumnINeed
FROM [dbo].tableA
LEFT OUTER JOIN [dbo].tableB
ON [dbo].tableA.myDateColumn > '1/1/2009'
AND [dbo].tableA.myColumn = FormatColumnOneWay([dbo].tableB.myColumn)
UNION ALL
SELECT [dbo].tableB.theColumnINeed
FROM [dbo].tableA
LEFT OUTER JOIN [dbo].tableB
ON [dbo].tableA.myDateColumn <= '1/1/2009'
AND [dbo].tableA.myColumn = FormatColumnAnotherWay([dbo].tableB.myColumn)
但是如果FormatColumnOneWay / FormatColumnAnotherWay是函数或字段表达式,那么可能会在[myColumn]上排除使用inxdex,尽管仍然应该使用myDateColumn上的任何索引
然而,它可能有助于理解FormatColumnOneWay / FormatColumnAnotherWay逻辑是什么,因为已知可以实现更好的优化
需要注意的事项:
UNION ALL不会删除任何重复项(与UNION不同)。由于这两个子查询是互斥的,因此可以保存UNION将使其删除重复项的SORT步骤。
你不应该使用'1/1/2009'样式用于字符串日期,你应该使用'yyyymmdd'样式而不使用斜杠或连字符(你也可以使用带参数的CONVERT来明确指示字符串在d中/ m / y或m / d / y样式
答案 2 :(得分:0)
从[dbo]
前缀,我相信您正在使用SQL Server。虽然我没有太多使用经验,但您可以将这两个字段转换为特定的日期格式:
select * from tableA
Left Outer join tableB
On CONVERT(CHAR(8), tableA.myColumn, 112) = CONVERT(CHAR(8), tableB.myColumn, 112)
使用适当的日期格式化功能,同样适用于任何DBMS。
我不了解SQL Server,但在Oracle中,您可以为连接表达式创建索引。
答案 3 :(得分:0)
在SQL Server中,您使用CASE,例如:
SELECT *
FROM TableA
INNER JOIN TableB on TableA.Column=
CASE WHEN TableA.RecordDate>'1/2/08'
THEN FormatCoumn(TableB.Column)
ELSE FormatColumnOtherWat(TableB.Column)
END
答案 4 :(得分:0)
您知道这对性能有害,因为您无法正确使用索引吗?
你可以使用CASE语句kludge或...你可以去修复数据,这样你就可以使用索引,它会快很多倍
答案 5 :(得分:0)
好吧,您可以使用子查询在连接之前正确格式化任一表中的数据。
SELECT
newB.columnINeed
FROM
tableA AS A
LEFT OUTER JOIN (
SELECT
columnINeed
, CASE WHEN myColumn > '1/1/2009' THEN FormatColumnOneWay(myColumn)
ELSE FormatColumnAnotherWay(myColumn)
END AS myColumn
FROM
tableB
) AS NewB ON A.myColumn = B.myColumn
如果性能很重要,您可以使用索引视图(基于子查询),而不是将子查询硬编码到整个查询中。
答案 6 :(得分:0)
我同意CASE
语法更适合阅读目的,但我不知道运行时间是否有任何显着差异。
“正确”的事情,实际上,是重新做,并做正确的事情。您的日期应存储在datetime
列中,将tableB中的所有日期迁移到datetime列可能会有很多好处。你可以这样做,其中包括:
TableB
的{{1}}。答案 7 :(得分:0)
好的,举起来。该列的实际数据类型是什么?我猜它不是DateTime,因为你没有真正控制格式......它只是存储一个日期。它可以是CAST还是CONVERT到日期时间?
所以你可能想要
left outer join tableb on tableA.myColumn = CAST(tableb.MyColumn as DateTime)
这样你就不会匹配一个字符串,但实际的日期应该更可靠。它也更简单,更容易阅读。真正的问题是为什么日期没有作为DateTime存储在第一个地方......