JOS*_*Ftw 5 sql-server aggregate sql-server-2016
我有以下表结构
AccountID Property Value
123456 Status Active
123456 City Los Angeles
123456 RegistrationDate 2018-05-11 11:30:14.000
543210 Status Active
543210 City Las Vegas
543210 RegistrationDate 2018-05-11 11:13:14.000
888888 Status Inactive
888888 City Toronto
888888 RegistrationDate 2015-05-12 11:13:14.000
Run Code Online (Sandbox Code Playgroud)
我希望能够选择 Property == Status 和 Value == Active And Property == RegistrationDate and Value == 2018-05-11 11:30:14.000 的所有行
我想我需要做某种 GROUP BY 然后选择那个聚合,但我无法理解它(我的 sql 真的很生疏)。
我想要上面“查询”的以下输出
AccountID Status RegistrationDate
123456 Active 2018-05-11 11:30:14.000
543210 Active 2018-05-11 11:30:14.000
Run Code Online (Sandbox Code Playgroud)
如果所有列都存在于同一行中,我会这样写:
SELECT AccountID FROM Property
WHERE Status = 'Active'
AND RegistrationDate = '2018-05-11 11:30:14.000'
Run Code Online (Sandbox Code Playgroud)
ype*_*eᵀᴹ 10
该设计模式称为 EAV(实体-属性-值)。GROUP BY
这种设计通常需要具有多个连接的 或 查询:
SELECT
a.AccountID
FROM
tbl AS a
JOIN tbl AS b
ON a.AccountID = b.AccountID
WHERE
a.Property = 'Status'
AND a.Value = 'Active'
AND b.Property = 'RegistrationDate'
AND b.Value = '2018-05-11 11:30:14.000' ;
Run Code Online (Sandbox Code Playgroud)
另一种表达方式是使用PIVOT
将 EAV 结构转换为表格形式。鉴于:
DROP TABLE IF EXISTS dbo.EAV;
CREATE TABLE dbo.EAV
(
AccountID integer NOT NULL,
Property varchar(30) NOT NULL,
Value sql_variant NULL
);
INSERT dbo.EAV
(AccountID, Property, [Value])
VALUES
(123456, 'Status', CONVERT(sql_variant, 'Active')),
(123456, 'City', CONVERT(sql_variant, 'Los Angeles')),
(123456, 'RegistrationDate', CONVERT(sql_variant, CONVERT(datetime, '2018-05-11 11:30:14.000', 121))),
(543210, 'Status', CONVERT(sql_variant, 'Active')),
(543210, 'City', CONVERT(sql_variant, 'Las Vegas')),
(543210, 'RegistrationDate', CONVERT(sql_variant, CONVERT(datetime, '2018-05-11 11:13:14.000', 121))),
(888888, 'Status', CONVERT(sql_variant, 'Inactive')),
(888888, 'City', CONVERT(sql_variant, 'Toronto')),
(888888, 'RegistrationDate', CONVERT(sql_variant, CONVERT(datetime, '2015-05-12 11:13:14.000', 121)));
Run Code Online (Sandbox Code Playgroud)
一个示例查询是:
SELECT
P.AccountID,
P.[Status],
P.City,
P.RegistrationDate
FROM dbo.EAV AS E
PIVOT (MAX([Value])
FOR Property IN
(
[Status],
[City],
[RegistrationDate])
) AS P
WHERE
P.[Status] = CONVERT(sql_variant, 'Active')
AND P.RegistrationDate = CONVERT(sql_variant, CONVERT(datetime, '2018-05-11 11:30:14.000', 121));
Run Code Online (Sandbox Code Playgroud)
结果:
帐号| 状态 | 城市 | 注册日期 --------: | :----- | :---------- | :------------------ 123456 | 活跃 | 洛杉矶 | 11/05/2018 11:30:14
db<>在这里摆弄