使用 SQL WITH 子句,然后在一个过程中将其与 SELECT 语句合并
Using SQL WITH clause then merging it with SELECT statement in one procedure
我有一个 table,其中 XML 列的类型为 nvarchar(max) ContactInformationXML
。我设法解析此列以使用此查询 CountryMarket
获取我想要的数据:
WITH CastToXML AS (
SELECT ContactInformationXML, TRY_CAST(ContactInformationXML AS xml) AS x
FROM Archive_ProgUsers
WHERE ContactInformationXML IS NOT NULL AND ContactInformationXML <> '' AND ContactInformationXML <> 'Admin - Old Program in Use' AND ContactInformationXML <> 'Admin - Admin Edits'
)
SELECT h.p.value('(/user/contact/@CountryMarket)[1]','nvarchar(max)') AS CountryMarket
FROM CastToXML
cross apply x.nodes('/user/contact[1]') AS h(p)
但是,既然我有了该列,我需要将它与同一过程中的另一个查询结合起来以显示一个 table。这是第二个查询:
SELECT DISTINCT
user_id,
email,
app_id,
ContactInformationXML,
install_code,
programStarts
FROM Archive_ProgUsers
INNER JOIN Archive_Installations ON Archive_ProgUsers.id = Archive_Installations.user_id
INNER JOIN (
SELECT DISTINCT inst_id
, COUNT(CASE WHEN Archive_Hits.type <> 'New' AND Archive_Hits.accessed_on BETWEEN CAST(@startdate AS DATE) AND CAST(@enddate AS DATE) THEN 1 END) AS programStarts
FROM Archive_Hits
GROUP BY Archive_Hits.inst_id
) AS hitsCount ON hitsCount.inst_id = Archive_Installations.id
WHERE programStarts > 0
ORDER BY programStarts DESC
我不能使用 UNION 或 UNION ALL,因为我必须在每个列表中有相同数量的表达式。
如何将这 2 个查询合并到一个过程中,returns 一个结果 table 看起来像这样?
更新
联系信息示例XML 数据:
<user Userid="John Smith"> <contact FirstName="John" LastName="Smith" RegistrationEmailAddress="j.smith@example.com" DisplayEmailAddress="j.smith@example.com" Company="Google" Title="" PhoneNum="+6666666666" FaxNum="" Address1="example USA, 77" Address2="" City="Earth" StateName="testing;" StateCode="USA" ZipCode="00000" CountryCode="US" CountryMarket="North America" DateModified="2020-03-16T16:35:00"/> </user>
不知道联系信息 XML 的结构,很难猜测结果应该是什么,但根据您的查询,您可以这样做:
With CastToXML AS (
SELECT user_id, ContactInformationXML, TRY_CAST(ContactInformationXML AS xml) AS x
FROM Archive_ProgUsers
WHERE ContactInformationXML IS NOT NULL AND ContactInformationXML <> '' AND ContactInformationXML <> 'Admin - Old Program in Use' AND ContactInformationXML <> 'Admin - Admin Edits'
),
Market AS (
SELECT user_id, h.p.value('(/user/contact/@CountryMarket)[1]','nvarchar(max)') AS CountryMarket
FROM CastToXML
cross apply x.nodes('/user/contact[1]') AS h(p)
)
SELECT DISTINCT
user_id,
email,
app_id,
--ContactInformationXML,
install_code,
programStarts,
CountryMarket
FROM Archive_ProgUsers
INNER JOIN Archive_Installations ON Archive_ProgUsers.id = Archive_Installations.user_id
INNER JOIN (
SELECT DISTINCT inst_id
, COUNT(CASE WHEN Archive_Hits.type <> 'New' AND Archive_Hits.accessed_on BETWEEN CAST(@startdate AS DATE) AND CAST(@enddate AS DATE) THEN 1 END) AS programStarts
FROM Archive_Hits
GROUP BY Archive_Hits.inst_id
) AS hitsCount ON hitsCount.inst_id = Archive_Installations.id
LEFT JOIN Market
ON Market.user_id = Archive_ProgUsers.user_id
WHERE programStarts > 0
ORDER BY programStarts DESC
您似乎只有一个值要从 XML 中提取出来。所以你可以非常简单地做到这一点,将 TRY_CAST
放在 CROSS APPLY
中并在其上使用 .values
。
您也不需要 WHERE
,因为在这些情况下 TRY_CAST
将 return null
SELECT
user_id,
email,
app_id,
ContactInformationXML = v.x.value('(/user/contact/@CountryMarket)[1]','nvarchar(max)'),
install_code,
programStarts
FROM Archive_ProgUsers
INNER JOIN Archive_Installations ON Archive_ProgUsers.id = Archive_Installations.user_id
INNER JOIN (
SELECT inst_id
, COUNT(CASE WHEN Archive_Hits.type <> 'New' AND Archive_Hits.accessed_on BETWEEN CAST(@startdate AS DATE) AND CAST(@enddate AS DATE) THEN 1 END) AS programStarts
FROM Archive_Hits
GROUP BY Archive_Hits.inst_id
) AS hitsCount ON hitsCount.inst_id = Archive_Installations.id
CROSS APPLY (VALUES (TRY_CAST(ContactInformationXML AS xml)) ) v(x)
WHERE programStarts > 0
ORDER BY programStarts DESC
我建议您重新考虑那些 DISTINCT
。它们可能是不必要的。如果您得到重复项,您应该仔细查看您的联接。不要只是扔 DISTINCT
来消除重复项。
我有一个 table,其中 XML 列的类型为 nvarchar(max) ContactInformationXML
。我设法解析此列以使用此查询 CountryMarket
获取我想要的数据:
WITH CastToXML AS (
SELECT ContactInformationXML, TRY_CAST(ContactInformationXML AS xml) AS x
FROM Archive_ProgUsers
WHERE ContactInformationXML IS NOT NULL AND ContactInformationXML <> '' AND ContactInformationXML <> 'Admin - Old Program in Use' AND ContactInformationXML <> 'Admin - Admin Edits'
)
SELECT h.p.value('(/user/contact/@CountryMarket)[1]','nvarchar(max)') AS CountryMarket
FROM CastToXML
cross apply x.nodes('/user/contact[1]') AS h(p)
但是,既然我有了该列,我需要将它与同一过程中的另一个查询结合起来以显示一个 table。这是第二个查询:
SELECT DISTINCT
user_id,
email,
app_id,
ContactInformationXML,
install_code,
programStarts
FROM Archive_ProgUsers
INNER JOIN Archive_Installations ON Archive_ProgUsers.id = Archive_Installations.user_id
INNER JOIN (
SELECT DISTINCT inst_id
, COUNT(CASE WHEN Archive_Hits.type <> 'New' AND Archive_Hits.accessed_on BETWEEN CAST(@startdate AS DATE) AND CAST(@enddate AS DATE) THEN 1 END) AS programStarts
FROM Archive_Hits
GROUP BY Archive_Hits.inst_id
) AS hitsCount ON hitsCount.inst_id = Archive_Installations.id
WHERE programStarts > 0
ORDER BY programStarts DESC
我不能使用 UNION 或 UNION ALL,因为我必须在每个列表中有相同数量的表达式。
如何将这 2 个查询合并到一个过程中,returns 一个结果 table 看起来像这样?
更新 联系信息示例XML 数据:
<user Userid="John Smith"> <contact FirstName="John" LastName="Smith" RegistrationEmailAddress="j.smith@example.com" DisplayEmailAddress="j.smith@example.com" Company="Google" Title="" PhoneNum="+6666666666" FaxNum="" Address1="example USA, 77" Address2="" City="Earth" StateName="testing;" StateCode="USA" ZipCode="00000" CountryCode="US" CountryMarket="North America" DateModified="2020-03-16T16:35:00"/> </user>
不知道联系信息 XML 的结构,很难猜测结果应该是什么,但根据您的查询,您可以这样做:
With CastToXML AS (
SELECT user_id, ContactInformationXML, TRY_CAST(ContactInformationXML AS xml) AS x
FROM Archive_ProgUsers
WHERE ContactInformationXML IS NOT NULL AND ContactInformationXML <> '' AND ContactInformationXML <> 'Admin - Old Program in Use' AND ContactInformationXML <> 'Admin - Admin Edits'
),
Market AS (
SELECT user_id, h.p.value('(/user/contact/@CountryMarket)[1]','nvarchar(max)') AS CountryMarket
FROM CastToXML
cross apply x.nodes('/user/contact[1]') AS h(p)
)
SELECT DISTINCT
user_id,
email,
app_id,
--ContactInformationXML,
install_code,
programStarts,
CountryMarket
FROM Archive_ProgUsers
INNER JOIN Archive_Installations ON Archive_ProgUsers.id = Archive_Installations.user_id
INNER JOIN (
SELECT DISTINCT inst_id
, COUNT(CASE WHEN Archive_Hits.type <> 'New' AND Archive_Hits.accessed_on BETWEEN CAST(@startdate AS DATE) AND CAST(@enddate AS DATE) THEN 1 END) AS programStarts
FROM Archive_Hits
GROUP BY Archive_Hits.inst_id
) AS hitsCount ON hitsCount.inst_id = Archive_Installations.id
LEFT JOIN Market
ON Market.user_id = Archive_ProgUsers.user_id
WHERE programStarts > 0
ORDER BY programStarts DESC
您似乎只有一个值要从 XML 中提取出来。所以你可以非常简单地做到这一点,将 TRY_CAST
放在 CROSS APPLY
中并在其上使用 .values
。
您也不需要 WHERE
,因为在这些情况下 TRY_CAST
将 return null
SELECT
user_id,
email,
app_id,
ContactInformationXML = v.x.value('(/user/contact/@CountryMarket)[1]','nvarchar(max)'),
install_code,
programStarts
FROM Archive_ProgUsers
INNER JOIN Archive_Installations ON Archive_ProgUsers.id = Archive_Installations.user_id
INNER JOIN (
SELECT inst_id
, COUNT(CASE WHEN Archive_Hits.type <> 'New' AND Archive_Hits.accessed_on BETWEEN CAST(@startdate AS DATE) AND CAST(@enddate AS DATE) THEN 1 END) AS programStarts
FROM Archive_Hits
GROUP BY Archive_Hits.inst_id
) AS hitsCount ON hitsCount.inst_id = Archive_Installations.id
CROSS APPLY (VALUES (TRY_CAST(ContactInformationXML AS xml)) ) v(x)
WHERE programStarts > 0
ORDER BY programStarts DESC
我建议您重新考虑那些 DISTINCT
。它们可能是不必要的。如果您得到重复项,您应该仔细查看您的联接。不要只是扔 DISTINCT
来消除重复项。