我在SO上看到过类似的错误,但我没有找到解决我的问题的方法。
我有一个SQL查询像:
SELECT DISTINCT
a.maxa ,
b.mahuyen ,
a.tenxa ,
b.tenhuyen ,
ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a ,
quanhuyen b
LEFT OUTER JOIN ( SELECT maxa ,
COUNT(*) AS tong
FROM khaosat
WHERE CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
AND
'Sep 5 2011'
GROUP BY maxa
) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa <> '99'
AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;
当我执行这个查询时,错误结果是:
无法绑定多部分标识符“a.maxa”。为什么?
P/s:如果我把查询分成2个单独的查询,它运行正常。
SELECT DISTINCT
a.maxa ,
b.mahuyen ,
a.tenxa ,
b.tenhuyen
FROM phuongxa a ,
quanhuyen b
WHERE a.maxa <> '99'
AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;
and
SELECT maxa ,
COUNT(*) AS tong
FROM khaosat
WHERE CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
AND 'Sep 5 2011'
GROUP BY maxa;
您混合了隐式连接和显式连接。这是允许的,但您需要知道如何正确地做到这一点。
问题是,显式连接(使用JOIN关键字实现的连接)优先于隐式连接('逗号'连接,其中连接条件在where子句中指定)。
以下是你的问题的提纲:
SELECT
…
FROM a, b LEFT JOIN dkcd ON …
WHERE …
你可能希望它是这样的:
SELECT
…
FROM (a, b) LEFT JOIN dkcd ON …
WHERE …
也就是说,表a和b的组合与表dkcd连接。事实上,正在发生的事情是
SELECT
…
FROM a, (b LEFT JOIN dkcd ON …)
WHERE …
也就是说,正如您可能已经理解的那样,dkcd是专门针对b且仅针对b连接的,然后连接的结果与a结合,并使用WHERE子句进一步筛选。在这种情况下,ON子句中对a的任何引用都是无效的,此时a是未知的。这就是为什么您会得到错误消息。
如果我是你,我可能会尝试重写这个查询,一个可能的解决方案可能是:
SELECT DISTINCT
a.maxa,
b.mahuyen,
a.tenxa,
b.tenhuyen,
ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a
INNER JOIN quanhuyen b ON LEFT(a.maxa, 2) = b.mahuyen
LEFT OUTER JOIN (
SELECT
maxa,
COUNT(*) AS tong
FROM khaosat
WHERE CONVERT(datetime, ngaylap, 103) BETWEEN 'Sep 1 2011' AND 'Sep 5 2011'
GROUP BY maxa
) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa <> '99'
ORDER BY a.maxa
这里首先连接表a和b,然后将结果连接到dkcd。基本上,这是与您的查询相同的查询,只是对其中一个连接使用了不同的语法,这产生了很大的不同:dkcd的连接条件中的引用a.maxa现在是绝对有效的。
正如@Aaron Bertrand所正确指出的,您可能应该在ORDER BY子句中使用特定的别名限定maxa,可能是a。
我也在这个错误中挣扎,最后用了和答案相同的策略。我的回答只是为了确认这是一种应该有效的策略。
这是一个例子,我首先在两个表之间做一个内部连接,我知道得到数据,然后在表上做两个左外部连接,这些表可能有相应的行,可以为空。您混合使用内部连接和外部连接来获得跨表数据的结果,而不是在表之间使用默认的逗号分隔语法,从而错过所需连接中的行。
use somedatabase
go
select o.operationid, o.operatingdate, p.pasid, p.name as patientname, o.operationalunitid, f.name as operasjonsprogram, o.theaterid as stueid, t.name as stuenavn, o.status as operasjonsstatus from operation o
inner join patient p on o.operationid = p.operationid
left outer join freshorganizationalunit f on f.freshorganizationalunitid = o.operationalunitid
left outer join theater t on t.theaterid = o.theaterid
where (p.Name like '%Male[0-9]%' or p.Name like '%KFemale [0-9]%')
首先:在希望进行数据匹配的表之间进行内部连接。
第二部分:继续使用外部连接,尝试检索其他表中的数据,
但是,如果表外部连接没有得到相应的数据,或者与您在on谓词/条件中设置的条件匹配,这将不会过滤出您的结果集。