我对SQL非常陌生并且都是自学成才所以请在技术过时时牢记这一点!
我正在使用教会数据库。我们有一张桌子,可以为家庭成员分配家庭ID。我有一个包含所有系列ID的表,并且有一个列,其中包含与该系列ID关联的唯一人员ID。当我针对查找特定系列ID的表运行查询时,我会为与该系列ID关联的每个唯一身份ID获取一行。
我需要做的是将这些家庭组合成一行,在一列中显示成人的名字,在另一列中显示孩子的名字。然后是列中的姓氏和列中的地址。
当我使用它时,我可以成功地做到这一点:
DECLARE @FirstNames VARCHAR (MAX)
DECLARE @Children VARCHAR (MAX)
DECLARE @Address VARCHAR (MAX)
DECLARE @LastName VARCHAR (MAX)
SELECT @FirstNames = COALESCE(@FirstNames+', ','') + pb.first_name,
@Address = pb.Address,
@LastName = pb.last_name
FROM core_v_person_basic pb
JOIN core_family_member fm ON fm.person_id = pb.person_id
WHERE fm.role_luid = 29
AND fm.family_id = 13783
SELECT @Children = COALESCE(@Children+', ','') + pb.first_name
FROM core_v_person_basic pb
JOIN core_family_member fm ON fm.person_id = pb.person_id
WHERE fm.role_luid = 31
AND fm.family_id = 13783
SELECT
@FirstNames AS 'First Names',
@LastName AS 'Last Name',
@Children AS 'Children',
@Address AS 'Address'
但问题是这只适用于一个家庭ID。我希望能够以这种方式显示所有族ID,或者显示一组特定的家庭ID。例如,我可能想要显示某个类中将来自不同表的所有族。
我需要一个足够灵活的解决方案,让我可以根据需要更改它以在结果中添加不同的列。
非常感谢您的帮助!
更新 这是我从Dimitar Kyuchukov的答案修改的查询: - 为了样本的目的模拟表格(你可以用代码中的表名替换这些变量,直到样本结束):
DECLARE @core_family_member AS TABLE
(family_id int,
person_id int,
date_created datetime,
date_modified datetime,
created_by varchar(50),
modified_by varchar(50),
role_luid int,
organization_id int)
DECLARE @core_v_person_basic AS TABLE (
person_id int,
guid uniqueidentifier,
suffix varchar(50),
nick_name nvarchar(50),
first_name nvarchar(50),
last_name nvarchar(50),
birth_date datetime,
address_id int,
Address varchar(201),
street_address_1 varchar(100),
street_address_2 varchar(100),
city varchar(64),
state varchar(12),
postal_code varchar(24),
member_status_luid int,
member_status varchar(50),
record_status varchar(8),
gender varchar(1),
marital_status_luid int,
marital_status varchar(50),
home_phone varchar(50),
list_home_phone varchar(50),
business_phone varchar(50),
list_business_phone varchar(50),
cell_phone varchar(50),
list_cell_phone varchar(50),
email varchar(80),
area_id int,
area_name varchar(100),
organization_id int,
photo_guid varchar(80),
envelope_number int,
restricted bit)
INSERT INTO
@core_v_person_basic
SELECT * FROM core_v_person_basic
INSERT INTO
@core_family_member
SELECT * FROM core_family_member
-- Here children and parents are selected separately with a family ID to join by (these are called CTE-s for Common Table Expression - they will make the final statement more clear):
;WITH
Children AS (
SELECT
fm.family_id,
pb.first_name AS child_first_name
FROM
@core_v_person_basic pb
INNER JOIN @core_family_member fm
ON fm.person_id = pb.person_id
WHERE
fm.role_luid = 31
),
Parents AS (
SELECT
fm.family_id,
pb.first_name AS parent_first_name
FROM
@core_v_person_basic pb
INNER JOIN @core_family_member fm
ON fm.person_id = pb.person_id
WHERE
fm.role_luid = 29
),
Address AS (
SELECT
pb.address AS 'Address'
FROM
@core_v_person_basic pb)
-- Here stuff() function is used to concatenate the members grouped by family ID - basically an XML is "stuffed" similar to your variables and then the ready value is taken using the value() function:
SELECT
stuff((
SELECT
', ' + p.parent_first_name
FROM
Parents p
WHERE
f.family_id = p.family_id
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'VARCHAR(MAX)')
, 1, 1, '') AS parents_names,
stuff((
SELECT
', ' + c.child_first_name
FROM
Children c
WHERE
f.family_id = c.family_id
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'VARCHAR(MAX)')
, 1, 1, '') AS children_names
FROM
Parents f
GROUP BY
f.family_id
这更接近我的需要,但我仍然无法添加任何已有的列。这似乎是因为Group By语法。任何有关如何调出额外列的帮助都会很棒!
解<!/ em>的 我按照我的需要工作了!这是包含更多列和信息的工作查询!
WITH
Children AS (
SELECT
fm.family_id,
pb.first_name AS child_first_name
FROM
core_v_person_basic pb
INNER JOIN core_family_member fm
ON fm.person_id = pb.person_id
WHERE
fm.role_luid = 31
),
Parents AS (
SELECT
fm.family_id,
pb.Address,
pb.city,
pb.state,
pb.postal_code,
pb.record_status,
pb.last_name,
pb.first_name AS parent_first_name
FROM
core_v_person_basic pb
INNER JOIN core_family_member fm
ON fm.person_id = pb.person_id
WHERE
fm.role_luid = 29
),
RecordStatus AS (
SELECT
fm.family_id,
pb.record_status AS record_status
FROM
core_v_person_basic pb
JOIN core_family_member fm On fm.person_id = pb.person_id
),
InactiveReason AS (
SELECT
fm.family_id,
ir.inactive_reason_value AS inactive_reason
FROM
core_person cp
JOIN core_family_member fm ON cp.person_id = fm.person_id
JOIN core_v_inactive_reason ir ON ir.inactive_reason_id = cp.inactive_reason_luid
)
-- Here stuff() function is used to concatenate the members grouped by family ID - basically an XML is "stuffed" similar to your variables and then the ready value is taken using the value() function:
SELECT
stuff((
SELECT
', ' + p.parent_first_name
FROM
Parents p
WHERE
f.family_id = p.family_id
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'VARCHAR(MAX)')
, 1, 1, '') AS 'First Name(s)',
f.last_name,
stuff((
SELECT
', ' + c.child_first_name
FROM
Children c
WHERE
f.family_id = c.family_id
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'VARCHAR(MAX)')
, 1, 1, '') AS 'Children',
f.Address,
f.city,
f.state,
f.postal_code,
STUFF((
SELECT
', ' + r.record_status
FROM
RecordStatus r
WHERE
f.family_id = r.family_id
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'VARCHAR(MAX)')
, 1, 1, '') AS 'Record Status',
STUFF((
SELECT
', ' + i.inactive_reason
FROM
InactiveReason i
WHERE
f.family_id = i.family_id
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'VARCHAR(MAX)')
, 1, 1, '') AS 'Record Status'
FROM
Parents f
GROUP BY
f.family_id,
f.Address,
f.city,
f.state,
f.postal_code,
f.last_name
感谢大家的帮助!
答案 0 :(得分:0)
您可以尝试使用stuff()
函数来连接按family_id分组的结果 - 这是一个示例,我认为它会返回您需要的内容。
我担心我不能让它变得更简单 - 遗憾的是,SQL服务器没有group_concat函数,stuff()
对于连接目的来说,读取或写入真的很难看。您可以向Children和Parents CTE添加更多列,但如果需要连接,则需要为每个新连接列添加单独的stuff()
调用。
-- Simulate your tables for sample's sake (you would replace these variables with your table names in the code till the end of the sample), this is just demo:
DECLARE @core_v_person_basic AS TABLE (
person_id INT,
first_name VARCHAR(30)
)
DECLARE @core_family_member AS TABLE (
person_id INT,
role_luid INT,
family_id INT
)
INSERT INTO
@core_v_person_basic
VALUES
--- family 1
(1, 'Alexander'),
(2, 'Diana'),
(3, 'Nick'),
(4, 'Betty'),
--- family 2
(5, 'Gustav'),
(6, 'Lory'),
(7, 'Peter'),
(8, 'Ally'),
--- family 3 (no children here)
(9, 'Chuck'),
(10, 'Sarah')
INSERT INTO
@core_family_member
VALUES
--- family 1
(1, 29, 1),
(2, 29, 1),
(3, 31, 1),
(4, 31, 1),
--- family 2
(5, 29, 2),
(6, 29, 2),
(7, 31, 2),
(8, 31, 2),
--- family 3
(9, 29, 3),
(10, 29, 3)
-- End of demo data preparation, below comes the actual sample.
-- Here children and parents are selected separately with a family ID to join by (these are called CTE-s for Common Table Expression - they will make the final statement more clear):
;WITH
Children AS (
SELECT
fm.family_id,
pb.first_name AS child_first_name
FROM
-- you should use your table names here, not the demo variables:
@core_v_person_basic pb
INNER JOIN @core_family_member fm
ON fm.person_id = pb.person_id
WHERE
fm.role_luid = 31
),
Parents AS (
SELECT
fm.family_id,
pb.first_name AS parent_first_name
FROM
-- you should use your table names here, not the demo variables:
@core_v_person_basic pb
INNER JOIN @core_family_member fm
ON fm.person_id = pb.person_id
WHERE
fm.role_luid = 29
)
-- Here stuff() function is used to concatenate the members grouped by family ID - basically an XML is "stuffed" similar to your variables and then the ready value is taken using the value() function:
SELECT
stuff((
SELECT
',' + p.parent_first_name
FROM
Parents p
WHERE
f.family_id = p.family_id
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'VARCHAR(MAX)')
, 1, 1, '') AS parents_names,
stuff((
SELECT
',' + c.child_first_name
FROM
Children c
WHERE
f.family_id = c.family_id
FOR XML PATH(''), TYPE
).value('(./text())[1]', 'VARCHAR(MAX)')
, 1, 1, '') AS children_names
FROM
Parents f
GROUP BY
family_id