在 SQL Server 2008r2 中有 sub-query return 多个字段
Have a sub-query return multiple fields in SQL Server 2008r2
我正在 Delphi 中做一些报告,我需要在单个查询中返回所有发票 header 信息。问题是 header 我需要的 4 个字段可能来自 4 个不同的地方,具体取决于主 table 中的值。我有以下(不起作用)作为我正在尝试做的事情的例子:
select t.ID, t.TRANSACTIONNUMBER, t.TRANSACTIONDATE,
a.ABBREVIATION, a.NAME, d.LINE1, d.LINE2, d.LINE3,
d.CITY, d.[STATE], d.ZIPCODE, tl.NAME COUNTRYNAME,
b.NAME BROKERNAME, t.ORIGIN, t.TRANSACTIONTYPE,
t.REFERENCESID, t.POSTED, t.DELETED, t.PROFORMA,
t.REMARKS, abs(t.AMOUNT) AMOUNT, c.CONVERSIONRATE,
c.ABBREVIATION CURRENCYABBR,
case t.ORIGIN
when 25 then (select VESSELID, VOYAGENUMBER, ARRIVALTIME, DEPARTURETIME from HMLOG where (ID = t.REFERENCESID))
when 26 then (select VESSELID, VOYAGENUMBER, ARRIVALTIME, DEPARTURETIME from HMLOG where (ID in (SELECT HMLOGID FROM CARGO_BOL WHERE ID = t.REFERENCESID)))
when 27 then (select VESSELID, VOYAGENUMBER, ARRIVALTIME, DEPARTURETIME from HMLOG where (ID in (SELECT HMLOGOUTID FROM CONTAINERLOG WHERE ID = t.REFERENCESID)))
when 28 then (select null VESSELID, null VOYAGENUMBER, null ARRIVALTIME, null DEPARTURETIME)
end
from [TRAN] t join
ACCOUNTS a on (t.ACCOUNTID = a.id) join
[ADDRESS] d on (t.MAILINGID = d.id) left join
ACCOUNTS b on (t.BRACCOUNTID = b.ID) join
TYPES_LIST tl on (d.COUNTRY = tl.ID) join
CURRENCY c on (t.ENTEREDCURRENCY = c.ID)
where (t.ID = 269017)
问题出在 case 语句中的 sub-queries。有没有人有任何优雅的方式来做到这一点?
更新:
我实际上想出了以下似乎有效的方法:
select t.ID, t.TRANSACTIONNUMBER, t.TRANSACTIONDATE,
a.ABBREVIATION, a.NAME, d.LINE1, d.LINE2, d.LINE3,
d.CITY, d.[STATE], d.ZIPCODE, tl.NAME COUNTRYNAME,
b.NAME BROKERNAME, t.ORIGIN, t.TRANSACTIONTYPE,
t.REFERENCESID, t.POSTED, t.DELETED, t.PROFORMA,
t.REMARKS, abs(t.AMOUNT) AMOUNT, c.CONVERSIONRATE,
c.ABBREVIATION CURRENCYABBR,
case t.ORIGIN when 25 then har.VESSELID when 26 then hbl.VESSELID when 27 then hcl.VESSELID when 28 then null end VESSELID,
case t.ORIGIN when 25 then va.VESSELNAME when 26 then vb.VESSELNAME when 27 then vc.VESSELNAME when 28 then null end VESSELNAME,
case t.ORIGIN when 25 then har.VOYAGENUMBER when 26 then hbl.VOYAGENUMBER when 27 then hcl.VOYAGENUMBER when 28 then null end VOYAGENUMBER,
case t.ORIGIN when 25 then har.ARRIVALTIME when 26 then hbl.ARRIVALTIME when 27 then hcl.ARRIVALTIME when 28 then null end ARRIVALTIME,
case t.ORIGIN when 25 then har.DEPARTURETIME when 26 then hbl.DEPARTURETIME when 27 then hcl.DEPARTURETIME when 28 then null end DEPARTURETIME
from [TRAN] t join
ACCOUNTS a on (t.ACCOUNTID = a.id) join
[ADDRESS] d on (t.MAILINGID = d.id) left join
ACCOUNTS b on (t.BRACCOUNTID = b.ID) join
TYPES_LIST tl on (d.COUNTRY = tl.ID) join
CURRENCY c on (t.ENTEREDCURRENCY = c.ID) left join
HMLOG har on (t.ORIGIN = 25) and (t.REFERENCESID = har.ID) left join
VESSEL va on (t.ORIGIN = 25) and (har.VESSELID = va.ID) left join
CARGO_BOL bl on (t.ORIGIN = 26) and (t.REFERENCESID = bl.ID) left join
HMLOG hbl on (t.ORIGIN = 26) and (bl.HMLOGID = hbl.ID) left join
VESSEL vb on (t.ORIGIN = 26) and (hbl.VESSELID = vb.ID) left join
CONTAINERLOG cl on (t.ORIGIN = 27) and (t.REFERENCESID = cl.ID) left join
HMLOG hcl on (t.ORIGIN = 27) and (cl.HMLOGOUTID = hcl.ID) left join
VESSEL vc on (t.ORIGIN = 27) and (hcl.VESSELID = vc.ID)
where (t.ID = 269017)
但我不确定这是否适用于所有情况(我以前从未在连接中使用过常量)或者是否还有更好的方法来实现我想要的。
你可以试试这个:
SELECT T.ID
,T.TRANSACTIONNUMBER
,T.TRANSACTIONDATE
,A.ABBREVIATION
,A.NAME
,D.LINE1
,D.LINE2
,D.LINE3
,D.CITY
,D.[STATE]
,D.ZIPCODE
,TL.NAME COUNTRYNAME
,B.NAME BROKERNAME
,T.ORIGIN
,T.TRANSACTIONTYPE
,T.REFERENCESID
,T.POSTED
,T.DELETED
,T.PROFORMA
,T.REMARKS
,ABS(T.AMOUNT) AMOUNT
,C.CONVERSIONRATE
,C.ABBREVIATION CURRENCYABBR
,COALESCE(H1.VESSELID, H2.VESSELID, H3.VESSELID) AS VESSELID
,COALESCE(H1.VOYAGENUMBER, H2.VOYAGENUMBER, H3.VOYAGENUMBER) AS VOYAGENUMBER
,COALESCE(H1.ARRIVALTIME, H2.ARRIVALTIME, H3.ARRIVALTIME) AS ARRIVALTIME
,COALESCE(H1.DEPARTURETIME, H2.DEPARTURETIME, H3.DEPARTURETIME) AS DEPARTURETIME
FROM [TRAN] T
INNER JOIN ACCOUNTS A
ON (T.ACCOUNTID = A.ID)
INNER JOIN [ADDRESS] D
ON (T.MAILINGID = D.ID)
INNER LEFT JOIN ACCOUNTS B
ON (T.BRACCOUNTID = B.ID)
INNER JOIN TYPES_LIST TL
ON (D.COUNTRY = TL.ID)
INNER JOIN CURRENCY C
ON (T.ENTEREDCURRENCY = C.ID)
LEFT JOIN HMLOG AS H1
ON H1.ID = T.REFERENCESID AND T.ORIGIN = 25
LEFT JOIN CARGO_BOL AS CB
INNER JOIN HMLOG AS H2
ON CB.HMLOGID = H2.ID
ON CB.ID = T.REFERENCESID AND T.ORIGIN = 26
LEFT JOIN CONTAINERLOG AS CL
INNER JOIN HMLOG AS H3
ON CL.HMLOGOUTID = H3.ID
ON CL.ID = T.REFERENCESID AND T.ORIGIN = 27
WHERE (T.ID = 269017)
我正在 Delphi 中做一些报告,我需要在单个查询中返回所有发票 header 信息。问题是 header 我需要的 4 个字段可能来自 4 个不同的地方,具体取决于主 table 中的值。我有以下(不起作用)作为我正在尝试做的事情的例子:
select t.ID, t.TRANSACTIONNUMBER, t.TRANSACTIONDATE,
a.ABBREVIATION, a.NAME, d.LINE1, d.LINE2, d.LINE3,
d.CITY, d.[STATE], d.ZIPCODE, tl.NAME COUNTRYNAME,
b.NAME BROKERNAME, t.ORIGIN, t.TRANSACTIONTYPE,
t.REFERENCESID, t.POSTED, t.DELETED, t.PROFORMA,
t.REMARKS, abs(t.AMOUNT) AMOUNT, c.CONVERSIONRATE,
c.ABBREVIATION CURRENCYABBR,
case t.ORIGIN
when 25 then (select VESSELID, VOYAGENUMBER, ARRIVALTIME, DEPARTURETIME from HMLOG where (ID = t.REFERENCESID))
when 26 then (select VESSELID, VOYAGENUMBER, ARRIVALTIME, DEPARTURETIME from HMLOG where (ID in (SELECT HMLOGID FROM CARGO_BOL WHERE ID = t.REFERENCESID)))
when 27 then (select VESSELID, VOYAGENUMBER, ARRIVALTIME, DEPARTURETIME from HMLOG where (ID in (SELECT HMLOGOUTID FROM CONTAINERLOG WHERE ID = t.REFERENCESID)))
when 28 then (select null VESSELID, null VOYAGENUMBER, null ARRIVALTIME, null DEPARTURETIME)
end
from [TRAN] t join
ACCOUNTS a on (t.ACCOUNTID = a.id) join
[ADDRESS] d on (t.MAILINGID = d.id) left join
ACCOUNTS b on (t.BRACCOUNTID = b.ID) join
TYPES_LIST tl on (d.COUNTRY = tl.ID) join
CURRENCY c on (t.ENTEREDCURRENCY = c.ID)
where (t.ID = 269017)
问题出在 case 语句中的 sub-queries。有没有人有任何优雅的方式来做到这一点?
更新:
我实际上想出了以下似乎有效的方法:
select t.ID, t.TRANSACTIONNUMBER, t.TRANSACTIONDATE,
a.ABBREVIATION, a.NAME, d.LINE1, d.LINE2, d.LINE3,
d.CITY, d.[STATE], d.ZIPCODE, tl.NAME COUNTRYNAME,
b.NAME BROKERNAME, t.ORIGIN, t.TRANSACTIONTYPE,
t.REFERENCESID, t.POSTED, t.DELETED, t.PROFORMA,
t.REMARKS, abs(t.AMOUNT) AMOUNT, c.CONVERSIONRATE,
c.ABBREVIATION CURRENCYABBR,
case t.ORIGIN when 25 then har.VESSELID when 26 then hbl.VESSELID when 27 then hcl.VESSELID when 28 then null end VESSELID,
case t.ORIGIN when 25 then va.VESSELNAME when 26 then vb.VESSELNAME when 27 then vc.VESSELNAME when 28 then null end VESSELNAME,
case t.ORIGIN when 25 then har.VOYAGENUMBER when 26 then hbl.VOYAGENUMBER when 27 then hcl.VOYAGENUMBER when 28 then null end VOYAGENUMBER,
case t.ORIGIN when 25 then har.ARRIVALTIME when 26 then hbl.ARRIVALTIME when 27 then hcl.ARRIVALTIME when 28 then null end ARRIVALTIME,
case t.ORIGIN when 25 then har.DEPARTURETIME when 26 then hbl.DEPARTURETIME when 27 then hcl.DEPARTURETIME when 28 then null end DEPARTURETIME
from [TRAN] t join
ACCOUNTS a on (t.ACCOUNTID = a.id) join
[ADDRESS] d on (t.MAILINGID = d.id) left join
ACCOUNTS b on (t.BRACCOUNTID = b.ID) join
TYPES_LIST tl on (d.COUNTRY = tl.ID) join
CURRENCY c on (t.ENTEREDCURRENCY = c.ID) left join
HMLOG har on (t.ORIGIN = 25) and (t.REFERENCESID = har.ID) left join
VESSEL va on (t.ORIGIN = 25) and (har.VESSELID = va.ID) left join
CARGO_BOL bl on (t.ORIGIN = 26) and (t.REFERENCESID = bl.ID) left join
HMLOG hbl on (t.ORIGIN = 26) and (bl.HMLOGID = hbl.ID) left join
VESSEL vb on (t.ORIGIN = 26) and (hbl.VESSELID = vb.ID) left join
CONTAINERLOG cl on (t.ORIGIN = 27) and (t.REFERENCESID = cl.ID) left join
HMLOG hcl on (t.ORIGIN = 27) and (cl.HMLOGOUTID = hcl.ID) left join
VESSEL vc on (t.ORIGIN = 27) and (hcl.VESSELID = vc.ID)
where (t.ID = 269017)
但我不确定这是否适用于所有情况(我以前从未在连接中使用过常量)或者是否还有更好的方法来实现我想要的。
你可以试试这个:
SELECT T.ID
,T.TRANSACTIONNUMBER
,T.TRANSACTIONDATE
,A.ABBREVIATION
,A.NAME
,D.LINE1
,D.LINE2
,D.LINE3
,D.CITY
,D.[STATE]
,D.ZIPCODE
,TL.NAME COUNTRYNAME
,B.NAME BROKERNAME
,T.ORIGIN
,T.TRANSACTIONTYPE
,T.REFERENCESID
,T.POSTED
,T.DELETED
,T.PROFORMA
,T.REMARKS
,ABS(T.AMOUNT) AMOUNT
,C.CONVERSIONRATE
,C.ABBREVIATION CURRENCYABBR
,COALESCE(H1.VESSELID, H2.VESSELID, H3.VESSELID) AS VESSELID
,COALESCE(H1.VOYAGENUMBER, H2.VOYAGENUMBER, H3.VOYAGENUMBER) AS VOYAGENUMBER
,COALESCE(H1.ARRIVALTIME, H2.ARRIVALTIME, H3.ARRIVALTIME) AS ARRIVALTIME
,COALESCE(H1.DEPARTURETIME, H2.DEPARTURETIME, H3.DEPARTURETIME) AS DEPARTURETIME
FROM [TRAN] T
INNER JOIN ACCOUNTS A
ON (T.ACCOUNTID = A.ID)
INNER JOIN [ADDRESS] D
ON (T.MAILINGID = D.ID)
INNER LEFT JOIN ACCOUNTS B
ON (T.BRACCOUNTID = B.ID)
INNER JOIN TYPES_LIST TL
ON (D.COUNTRY = TL.ID)
INNER JOIN CURRENCY C
ON (T.ENTEREDCURRENCY = C.ID)
LEFT JOIN HMLOG AS H1
ON H1.ID = T.REFERENCESID AND T.ORIGIN = 25
LEFT JOIN CARGO_BOL AS CB
INNER JOIN HMLOG AS H2
ON CB.HMLOGID = H2.ID
ON CB.ID = T.REFERENCESID AND T.ORIGIN = 26
LEFT JOIN CONTAINERLOG AS CL
INNER JOIN HMLOG AS H3
ON CL.HMLOGOUTID = H3.ID
ON CL.ID = T.REFERENCESID AND T.ORIGIN = 27
WHERE (T.ID = 269017)