尝试根据列的值获取不同的数据集
Trying to get a different data set depending on value of a column
我正在尝试构建一个需要条件的 SQL 语句,但我不确定如何去做。我查看了 If Else
语句,但它不能 return 超过 1 个值。
这是我能解释的最好的方式:
需要:
PT.Due_Date,
PO.Initials,
PO.[Order No],
PO.[Ordered by],
PO.Supplier,
PT.QTY,
PT.[Description]
这是令人困惑的地方(无论如何对我来说):
IF (PO.Part Delivered == 0)
{
/* All the required information has been retrieved. */
}
ELSE IF (PO.Part Delivered == 1)
{
/* Get the following information from POD: */
POD.[Delivery Date],
POD.Delivered,
POD.[Delivery Note],
POD.[Received_By ]
}
关于表之间的关系
[PO].[Order No] = [PT].[Order No]
[PT].[ID] = [POD].[Purchase_Table_ID]
POD和PO之间没有关系。
作为前言:不要将 SQL 的 SELECT
查询视为可以在 row-by-row 基础上执行逻辑分支的地方,而是将其视为仅使用 set-operations 和连接来描述查询的地方。
(在 row-by-row 的基础上在关系数据库中做 任何事情 无论如何都是 invariably terrible)。
那么你要做的是:
- 获取
PO
行中的 所有 行 PO.[Part Delivered] = 0
,我们称它们为 undeliveredPOs
.
- 分别获取
PO
行中PO.[Part Delivered] = 1
行的所有行,以及POD
行中的INNER JOIN
行,以及我们称这些为 deliveredPOsWithPODs
。
- 由于您没有向我们展示您的
CREATE TABLE
陈述,我假设您的 PO
和 POD
table 有 1:0-1
(one-to-zero-or-one) 关系使得:
PO.[Order No]
是 PO
的单数(非复合)PRIMARY KEY
.
POD.[Order No]
是 POD
的单数(非复合)PRIMARY KEY
并且 是 FOREIGN KEY
到 PO
.
- 此设计(您使用
FOREIGN KEY
列作为“子”table 中的 PRIMARY KEY
)是一个基本的 SQL 数据库 设计模式 从一开始就防止异常(即重复)“子”数据发生。
- 然后将
undeliveredPOs
和 deliveredPOsWithPODs
行连接(或更确切地说:UNION
)在一起。
- 由于
deliveredPOsWithPODs
的列多于 undeliveredPOs
,您需要将 NULL
值添加到 make-up 差异中。
如果您不熟悉:在 SQL 中,set-operators(UNION
、INTERSECT
、EXCEPT
)“垂直”连接数据行,而 JOIN
运算符“水平”连接数据列(如果有帮助的话)。
像这样,使用命名的 CTE:
WITH posWithPts AS (
SELECT
-- PO:
PO.Initials,
PO.[Order No],
PO.[Ordered by],
PO.Supplier,
-- PT:
PT.Due_Date,
PT.QTY,
PT.[Description]
FROM
PO
INNER JOIN PT ON PO.[SomeKey] = PT.[SomeKey]
),
undeliveredPOs AS (
SELECT
*
FROM
posWithPts
WHERE
[Part Delivered] = 0
),
deliveredPOsWithPODs AS (
SELECT
p.*,
POD.[Delivery Date],
POD.Delivered,
POD.[Delivery Note],
POD.[Received_By]
FROM
posWithPts AS p
INNER JOIN POD ON p.[Order No] = POD.[Order No]
WHERE
p.[Part Delivered] = 1
)
SELECT
u.*,
-- Add NULLs for columns absent in undeliveredPOs:
NULL AS [Delivery Date],
NULL AS Delivered,
NULL AS [Delivery Note],
NULL AS [Received_By]
FROM
undeliveredPOs AS u
UNION ALL /* Using `UNION ALL` instead of `UNION` for performance */
SELECT
d.*
FROM
deliveredPOsWithPODs AS d
我上面的 SQL 使用 *
来避免重复列名和提高可读性,但如果这变成 production-query 那么你应该总是明确列出所有列名(是的,这很乏味)并使用 WITH SCHEMABINDING
来防止数据库 table 设计更改破坏您的查询 and/or 导致不正确的结果 - 这在使用 UNION
和不匹配的列时最重要。
如果 query-maintenance 不是问题,那么可以内联最后 2 个 CTE(undeliveredPOs
和 deliveredPOsWithPODs
)(但因为 posWithPts
(源 view/CTE/derived-table/query) 被多次引用,它将保留为命名 CTE),因此上面的查询可以简化为这个
WITH posWithPts AS (
SELECT
-- PO:
PO.Initials,
PO.[Order No],
PO.[Ordered by],
PO.Supplier,
-- PT:
PT.Due_Date,
PT.QTY,
PT.[Description]
FROM
PO
INNER JOIN PT ON PO.[SomeKey] = PT.[SomeKey]
),
SELECT
n.*,
-- Add NULLs for columns absent in undeliveredPOs:
NULL AS [Delivery Date],
NULL AS Delivered,
NULL AS [Delivery Note],
NULL AS [Received_By]
FROM
posWithPts AS n
WHERE
n.[Part Delivered] = 0
UNION ALL
SELECT
d.*,
POD.[Delivery Date],
POD.Delivered,
POD.[Delivery Note],
POD.[Received_By]
FROM
posWithPts AS d
INNER JOIN POD ON p.[Order No] = POD.[Order No]
WHERE
d.[Part Delivered] = 1
我正在尝试构建一个需要条件的 SQL 语句,但我不确定如何去做。我查看了 If Else
语句,但它不能 return 超过 1 个值。
这是我能解释的最好的方式:
需要:
PT.Due_Date,
PO.Initials,
PO.[Order No],
PO.[Ordered by],
PO.Supplier,
PT.QTY,
PT.[Description]
这是令人困惑的地方(无论如何对我来说):
IF (PO.Part Delivered == 0)
{
/* All the required information has been retrieved. */
}
ELSE IF (PO.Part Delivered == 1)
{
/* Get the following information from POD: */
POD.[Delivery Date],
POD.Delivered,
POD.[Delivery Note],
POD.[Received_By ]
}
关于表之间的关系
[PO].[Order No] = [PT].[Order No]
[PT].[ID] = [POD].[Purchase_Table_ID]
POD和PO之间没有关系。
作为前言:不要将 SQL 的 SELECT
查询视为可以在 row-by-row 基础上执行逻辑分支的地方,而是将其视为仅使用 set-operations 和连接来描述查询的地方。
(在 row-by-row 的基础上在关系数据库中做 任何事情 无论如何都是 invariably terrible)。
那么你要做的是:
- 获取
PO
行中的 所有 行PO.[Part Delivered] = 0
,我们称它们为undeliveredPOs
. - 分别获取
PO
行中PO.[Part Delivered] = 1
行的所有行,以及POD
行中的INNER JOIN
行,以及我们称这些为deliveredPOsWithPODs
。- 由于您没有向我们展示您的
CREATE TABLE
陈述,我假设您的PO
和POD
table 有1:0-1
(one-to-zero-or-one) 关系使得:PO.[Order No]
是PO
的单数(非复合)PRIMARY KEY
.POD.[Order No]
是POD
的单数(非复合)PRIMARY KEY
并且 是FOREIGN KEY
到PO
.- 此设计(您使用
FOREIGN KEY
列作为“子”table 中的PRIMARY KEY
)是一个基本的 SQL 数据库 设计模式 从一开始就防止异常(即重复)“子”数据发生。
- 由于您没有向我们展示您的
- 然后将
undeliveredPOs
和deliveredPOsWithPODs
行连接(或更确切地说:UNION
)在一起。- 由于
deliveredPOsWithPODs
的列多于undeliveredPOs
,您需要将NULL
值添加到 make-up 差异中。
- 由于
如果您不熟悉:在 SQL 中,set-operators(UNION
、INTERSECT
、EXCEPT
)“垂直”连接数据行,而 JOIN
运算符“水平”连接数据列(如果有帮助的话)。
像这样,使用命名的 CTE:
WITH posWithPts AS (
SELECT
-- PO:
PO.Initials,
PO.[Order No],
PO.[Ordered by],
PO.Supplier,
-- PT:
PT.Due_Date,
PT.QTY,
PT.[Description]
FROM
PO
INNER JOIN PT ON PO.[SomeKey] = PT.[SomeKey]
),
undeliveredPOs AS (
SELECT
*
FROM
posWithPts
WHERE
[Part Delivered] = 0
),
deliveredPOsWithPODs AS (
SELECT
p.*,
POD.[Delivery Date],
POD.Delivered,
POD.[Delivery Note],
POD.[Received_By]
FROM
posWithPts AS p
INNER JOIN POD ON p.[Order No] = POD.[Order No]
WHERE
p.[Part Delivered] = 1
)
SELECT
u.*,
-- Add NULLs for columns absent in undeliveredPOs:
NULL AS [Delivery Date],
NULL AS Delivered,
NULL AS [Delivery Note],
NULL AS [Received_By]
FROM
undeliveredPOs AS u
UNION ALL /* Using `UNION ALL` instead of `UNION` for performance */
SELECT
d.*
FROM
deliveredPOsWithPODs AS d
我上面的 SQL 使用 *
来避免重复列名和提高可读性,但如果这变成 production-query 那么你应该总是明确列出所有列名(是的,这很乏味)并使用 WITH SCHEMABINDING
来防止数据库 table 设计更改破坏您的查询 and/or 导致不正确的结果 - 这在使用 UNION
和不匹配的列时最重要。
如果 query-maintenance 不是问题,那么可以内联最后 2 个 CTE(undeliveredPOs
和 deliveredPOsWithPODs
)(但因为 posWithPts
(源 view/CTE/derived-table/query) 被多次引用,它将保留为命名 CTE),因此上面的查询可以简化为这个
WITH posWithPts AS (
SELECT
-- PO:
PO.Initials,
PO.[Order No],
PO.[Ordered by],
PO.Supplier,
-- PT:
PT.Due_Date,
PT.QTY,
PT.[Description]
FROM
PO
INNER JOIN PT ON PO.[SomeKey] = PT.[SomeKey]
),
SELECT
n.*,
-- Add NULLs for columns absent in undeliveredPOs:
NULL AS [Delivery Date],
NULL AS Delivered,
NULL AS [Delivery Note],
NULL AS [Received_By]
FROM
posWithPts AS n
WHERE
n.[Part Delivered] = 0
UNION ALL
SELECT
d.*,
POD.[Delivery Date],
POD.Delivered,
POD.[Delivery Note],
POD.[Received_By]
FROM
posWithPts AS d
INNER JOIN POD ON p.[Order No] = POD.[Order No]
WHERE
d.[Part Delivered] = 1