对于SQL,我相对缺乏经验。我想知道使用CROSS APPLY
是否是下面SQL中的最佳选项?
我也认为我在重复工作。这有效,需要几分钟,但我的感觉是可以做得更好。
我正在看的三个主要表格非常大,我们每个人都会看到几百万行。各个插入语句每个都会拉回7-15K行。
DECLARE @Master TABLE
(
heyno NVARCHAR(12),
postcodestartdttm DATE,
postcodeenddttm DATE,
lzohistorypostcode NVARCHAR(25),
biactivitypostcode NVARCHAR(25),
activityenddttm DATE
);
INSERT INTO @Master
SELECT p.pasid,
par.startdttm,
par.enddttm,
pa.postcode AS LZOHistoryPostcode,
t.postcode AS BIActivityPostcode,
t.admitdate
FROM HEALTHBI.DBO.[lzo_patientaddressrole] AS par
INNER JOIN HEALTHBI.DBO.[lzo_patientaddress] AS pa
ON par.[addressoid] = pa.[oid]
AND pa.[status] = 'A'
INNER JOIN HEALTHBI.DBO.lzo_patient AS p
ON par.identifyingoid = p.oid
---
CROSS APPLY (SELECT i.admitdate,
i.postcode
FROM HEALTHBI_VIEWS.DBO.ip_admission i
WHERE i.patientoid = p.oid
AND i.admitdate > par.startdttm
AND i.admitdate >= '01 APRIL 2010'
AND i.admitdate < ISNULL(par.enddttm, '31-dec-4712')
AND par.[status] = 'A'
AND par.[identifyingtype] = 'Patient'
AND par.[rotypcode] = 'CC_USUALADD'
AND pa.[adtypcode] = 'Address'
AND pa.postcode <> i.postcode) AS t
INSERT INTO @Master
SELECT p.pasid,
par.startdttm,
par.enddttm,
pa.postcode AS LZOHistoryPostcode,
t.postcode AS BIActivityPostcode,
t.apptstartdate
FROM HEALTHBI.DBO.[lzo_patientaddressrole] AS par
INNER JOIN HEALTHBI.DBO.[lzo_patientaddress] AS pa
ON par.[addressoid] = pa.[oid]
AND pa.[status] = 'A'
INNER JOIN HEALTHBI.DBO.lzo_patient AS p
ON par.identifyingoid = p.oid
CROSS APPLY (SELECT i.apptstartdate,
i.postcode
FROM HEALTHBI_VIEWS.DBO.op_appointment i
WHERE i.patientoid = p.oid
AND i.apptstartdate > par.startdttm
AND i.apptstartdate >= '01 APRIL 2010'
AND i.apptstartdate < ISNULL(par.enddttm, '31-dec-4712')
AND par.[status] = 'A'
AND par.[identifyingtype] = 'Patient'
AND par.[rotypcode] = 'CC_USUALADD'
AND pa.[adtypcode] = 'Address'
AND pa.postcode <> i.postcode) AS t
INSERT INTO @Master
SELECT p.pasid,
par.startdttm,
par.enddttm,
pa.postcode AS LZOHistoryPostcode,
t.postcode AS BIActivityPostcode,
t.attenddate
FROM HEALTHBI.DBO.[lzo_patientaddressrole] AS par
INNER JOIN HEALTHBI.DBO.[lzo_patientaddress] AS pa
ON par.[addressoid] = pa.[oid]
AND pa.[status] = 'A'
INNER JOIN HEALTHBI.DBO.lzo_patient AS p
ON par.identifyingoid = p.oid
CROSS APPLY (SELECT i.attenddate,
i.postcode
FROM HEALTHBI_VIEWS.DBO.ed_attendance i
WHERE i.patientoid = p.oid
AND i.attenddate > par.startdttm
AND i.attenddate >= '01 APRIL 2010'
AND i.attenddate < ISNULL(par.enddttm, '31-dec-4712')
AND par.[status] = 'A'
AND par.[identifyingtype] = 'Patient'
AND par.[rotypcode] = 'CC_USUALADD'
AND pa.[adtypcode] = 'Address'
AND pa.postcode <> i.postcode) AS t
SELECT m.heyno,
m.lzohistorypostcode,
m.biactivitypostcode,
d.startofweek
FROM @Master m
INNER JOIN HEALTHBI_VIEWS.DBO.date_reference AS d
ON m.activityenddttm = d.datevalue
GROUP BY m.heyno,
m.lzohistorypostcode,
m.biactivitypostcode,
d.startofweek
ORDER BY m.heyno
答案 0 :(得分:-1)
您不想使用CROSS APPLY。这意味着与表值函数一起使用,它有点像光标,一次一条记录,这比设置操作慢得多。
我会尝试使用OUTER JOIN,如下所示。如果不更好地理解数据,很难做到正确,但似乎对于每个患者,您将获得多个入院日期和邮政编码,因此您可能会有一些重复,具体取决于ip_addmission视图返回的内容。如果不需要,您可以考虑使用GROUP BY仅返回最新的录取日期。
此外,避免在WHERE子句中使用函数,因为它们可能导致表扫描。我用下面的OR表达式替换了ISNULL。
SELECT p.pasid,
par.startdttm,
par.enddttm,
pa.postcode AS LZOHistoryPostcode,
i.postcode AS BIActivityPostcode,
i.admitdate
FROM HEALTHBI.DBO.[lzo_patientaddressrole] AS par
INNER JOIN HEALTHBI.DBO.[lzo_patientaddress] AS pa
ON par.[addressoid] = pa.[oid]
AND pa.[status] = 'A'
INNER JOIN HEALTHBI.DBO.lzo_patient AS p
ON par.identifyingoid = p.oid
---
LEFT OUTER JOIN HEALTHBI_VIEWS.DBO.ip_admission i
ON i.patientoid = p.oid
WHERE i.admitdate > par.startdttm
AND i.admitdate >= '01 APRIL 2010'
AND (i.admitdate < par.enddttm OR par.enddttm IS NULL)
AND par.[status] = 'A'
AND par.[identifyingtype] = 'Patient'
AND par.[rotypcode] = 'CC_USUALADD'
AND pa.[adtypcode] = 'Address'
AND pa.postcode <> i.postcode;