我有三张桌子需要加入。我可以加入其中两个并获得所需的结果,这个结果表需要与另一个表连接。
表1 :
+----------+---------+------+
| Username | Country | Team |
+----------+---------+------+
| abc | US | New |
| abc | CAN | New |
| bcd | US | Old |
+----------+---------+------+
表2 :
+----------+-------------+----------+------------+
| Username | CompanyCode | Document | Entry Date |
+----------+-------------+----------+------------+
| abc | 1 | 112 | 24/06/2014 |
| abc | 2 | 123 | 24/06/2014 |
| bcd | 3 | 456 | 24/06/2014 |
| efg | 4 | 984 | 24/06/2014 |
+----------+-------------+----------+------------+
我写了以下代码..
SELECT Username, CompanyCode, Document, IIF(MONTH([Entry Date]) = 6 AND YEAR([Entry Date]) = 2014, 'TRUE', 'FALSE') AS [Posted],
COALESCE(tNew.Country, 'not there') AS DC, COALESCE(tNew.Team, 'not there') AS Team FROM Table2
OUTER APPLY
(
SELECT TOP 1 Country, Team FROM Table1
WHERE Table1.[Username] = Table2.[Username]
) tNew
...导致( Table99 )......
+----------+--------------+----------+------------+--------+-----------+-----------+
| Username | Company Code | Document | Entry Date | Posted | Country | Team |
+----------+--------------+----------+------------+--------+-----------+-----------+
| abc | 1 | 112 | 24/06/2014 | TRUE | US | New |
| abc | 2 | 123 | 24/06/2014 | TRUE | US | New |
| bcd | 3 | 456 | 24/06/2014 | TRUE | US | Old |
| efg | 4 | 984 | 24/06/2014 | TRUE | not there | not there |
+----------+--------------+----------+------------+--------+-----------+-----------+
现在我有另一张桌子, Table3 :
+--------------+--------------+
| Company Code | Company Name |
+--------------+--------------+
| 1 | MS |
| 2 | APL |
| 3 | GOO |
| 4 | IBM |
| 5 | AMZ |
+--------------+--------------+
我想在Company Code
上将Table99与Table3一起加入,Document
WHERE Posted = TRUE AND Country <> 'not there'
的计数结果为......
+--------------+--------------+-----------------+
| Company Code | Company Name | Total Documents |
+--------------+--------------+-----------------+
| 1 | MS | 1 |
| 2 | APL | 1 |
| 3 | GOO | 1 |
| 4 | IBM | 0 |
| 5 | AMZ | 0 |
+--------------+--------------+-----------------+
答案 0 :(得分:2)
在LEFT JOIN
上执行Table3
和原始查询,然后使用条件SUM
来计算:
SELECT
t3.CompanyCode,
t3.CompanyName,
SUM(CASE WHEN t.Posted = 'TRUE' AND t.Country <> 'not there' THEN 1 ELSE 0 END)
FROM Table3 t3
LEFT JOIN (
SELECT
Username,
CompanyCode,
Document,
tnew.Country,
IIF(MONTH(EntryDate) = 6 AND YEAR(EntryDate) = 2014, 'TRUE', 'FALSE') AS [Posted],
COALESCE(tNew.Country, 'not there') AS DC,
COALESCE(tNew.Team, 'not there') AS Team
FROM Table2
OUTER APPLY(
SELECT TOP 1 Country, Team FROM Table1
WHERE Table1.[Username] = Table2.[Username]
) tNew
) t
ON t3.CompanyCode = t.CompanyCode
GROUP BY t3.CompanyCode, t3.CompanyName
ORDER BY t3.CompanyCode
答案 1 :(得分:1)
您可以将派生表视为真实表格来处理:
SELECT Username, Table2.CompanyCode, Document, IIF(MONTH([Entry Date]) = 6 AND YEAR([Entry Date]) = 2014, 'TRUE', 'FALSE') AS [Posted],
COALESCE(tNew.Country, 'not there') AS DC, COALESCE(tNew.Team, 'not there') AS Team FROM Table2
OUTER APPLY
(
SELECT TOP 1 Country, Team FROM Table1
WHERE Table1.[Username] = Table2.[Username]
) tNew
JOIN Table3 ON Table2.CompanyCode = Table3.CompanyCode
答案 2 :(得分:1)
我认为你的查询过于复杂了。 SQL的APPLY
运算符主要用于表值函数。更一般地说,它在两个表之间有用whenever there is no simple join condition。
在您的情况下,有一个非常简单的连接条件 - Username
和Table1
中的Table2
列。连接是SQL的本质,并且(通常)应该是您需要组合来自多个表的信息时的第一个调用端口。
所以在这种情况下,考虑到你需要实现的最终结果,你可以简单地使用两个左连接,没有APPLY
:
with PostedDocs as (
-- Define your requirements on the EntryDate value here
select CompanyCode
,Username
,Document
from Table2
where MONTH(EntryDate) = 6
and YEAR(EntryDate) = 2014
)
select CO.CompanyCode
,CO.CompanyName
,TotalDocuments =count(distinct case when USR.Country is null then null else DOC.Document end)
from Table3 CO
left join PostedDocs DOC on CO.CompanyCode=DOC.CompanyCode
left join Table1 USR on DOC.Username=USR.Username
group by CO.CompanyCode
,CO.CompanyName
order by CompanyCode asc
这为您在问题中提供的输入提供了所需的结果。它是一种更加面向SQL的思维方式,可能在大型表格上表现更好。
请注意,我以<{1}}开始。这样做是有道理的,因为在最终结果集中,您希望Table3
中的每一行都有一行。 Table3
使结果集更大,重复left joins
行,但随后我将其与Table3
重新汇总。
group by
函数不包含count
值,您可以在此处利用:左边连接不成功,值为null
,所以有无需转换为“不存在”等值。
一些切向点
通常在SQL中,我们不在列名中使用空格。我的答案与您的问题的列名略有不同,因为我将空格用于使列名更容易使用。
像我一样(DOC,USR,CO)给表格提供有意义的别名会很有帮助。
在原始代码中,此处:
null
除非包含OUTER APPLY
(
SELECT TOP 1 Country, Team FROM Table1
WHERE Table1.[Username] = Table2.[Username]
) tNew
子句,否则您应该知道SQL Server不保证一致的结果排序。因此,如果您继续使用这段代码,那么在将来的某个时刻,用户ORDER BY
返回的TOP 1
行可能是加拿大版,而不是美国版。我不确定这对你是否重要,但它可能很重要。一般来说,如果您关心一致的结果,那么使用abc
是不好的做法。您应该订购结果,或者使用TOP 1
或DISTINCT
功能,如果这些功能更适合您的情况。