在 ms sql 上对结果中的多个数据进行分组
Group multiple data in result on ms sql
我试图将多个结果查询组合在一行中,但没有找到除以下方法之外的其他方法。但我对这个解决方案并不真正满意。有没有更优雅的解决方案?
情境一经典n:m映射
Table 1 - 基础
Table 1 个与此相似
| ID_Basis(PK) | Name |
|--------------|------|
| 1 | One |
| 2 | Two |
| 3 | Three|
Table 2 - 映射
| ID_Basis(FK) | ID_AddOn (FK) | note |
|--------------|---------------|---------|
| 1 | 1 | some |
| 1 | 2 | example |
| 5 | 1 | more |
| 5 | 3 | random |
| 5 | 4 | data |
Table 3 - 插件
在这个特定案例中,这个实际上不用于检索数据,但为了完整性而显示
| ID_AddOn(PK) | AddOn Name|
|--------------|-----------|
| 1 | something |
| 2 | extra |
| 3 | ... |
| 4 | ... |
目标
现在我想使用 table 2 从 table 1 检索所有数据(与 table 3 的所有给定插件连接)并将所有注释连接起来结果中的一个字段。
| ID_Basis | Note |
|--------------|--------------------|
| 1 | some, example |
| 3 | more, random, data |
我得出以下解决方案:
SELECT b.ID_Basis,
b.Name,
m1.note + m2.note + m3.note + m4.note
FROM Basis AS b
LEFT OUTER JOIN Mapping AS m1 ON b.ID_Basis = m1.ID_Basis AND m1.ID_Addon = 1
LEFT OUTER JOIN Mapping AS m2 ON b.ID_Basis = m2.ID_Basis AND m2.ID_Addon = 2
LEFT OUTER JOIN Mapping AS m3 ON b.ID_Basis = m3.ID_Basis AND m3.ID_Addon = 3
LEFT OUTER JOIN Mapping AS m4 ON b.ID_Basis = m4.ID_Basis AND m4.ID_Addon = 4
只要有新的插件,这个解决方案就会失败。像 group_concat
这样的东西在这里不是更好吗?但是 MS SQL 不支持。
附件 - 完整示例
SELECT
dbo.Kalkulation.KalkulationsID_PK,
dbo.Kalkulationseingaben.Format_Breite,
dbo.Kalkulationseingaben.Format_Hoehe,
dbo.Kalkulationseingaben.Auflage,
dbo.Kalkulation.MaschinenID_FK,
dbo.Kalkulation.Druckverfahrensbezeichnung_FK,
dbo.Kalkulationsergebnis.Einkaufspreis,
dbo.Kalkulation.Ersteller_MitarbeiterID_FK,
dbo.Kalkulation.Bearbeiter_MitarbeiterID_FK,
Ersteller.Nutzername AS Ersteller_Nutzername,
Bearbeiter.Nutzername AS Bearbeiter_Nutzername,
dbo.Kalkulation.Erstellungsdatum,
dbo.Kalkulation.Bearbeitungsdatum,
dbo.Kalkulationseingaben.Freitexthinweis,
dbo.Kalkulation.Kunden_KontaktID_FK,
dbo.Kalkulation.Kunden_Kurzbezeichnung,
dbo.Kalkulation.MaterialID_FK,
dbo.Kalkulationseingaben.Version,
dbo.Maschine.Maschinenbezeichnung + ' ' + dbo.Maschine.Firmenbezeichnung_FK AS Maschine,
CAST(CASE WHEN zm1.ZuschlagsID_FK = 1 THEN 'Farbe ' + '(' + zm1.Auswahl + ') ' ELSE '' END AS nvarchar)
+ CAST(CASE WHEN zm2.ZuschlagsID_FK = 2 THEN 'Lack ' ELSE '' END AS nvarchar)
+ CAST(CASE WHEN zm8.ZuschlagsID_FK = 8 THEN 'Rückseitendruck ' ELSE '' END AS nvarchar)
+ CAST(CASE WHEN zm4.ZuschlagsID_FK = 4 THEN 'Kaltprägung ' ELSE '' END AS nvarchar)
+ CAST(CASE WHEN zm9.ZuschlagsID_FK = 9 THEN 'Kleberabtötung' ELSE '' END AS nvarchar) AS Druckeinstellung
FROM
dbo.Kalkulation
INNER JOIN
dbo.Kalkulationseingaben ON dbo.Kalkulation.KalkulationsID_PK = dbo.Kalkulationseingaben.KalkulationsID_FK
INNER JOIN
dbo.Kalkulationsergebnis ON dbo.Kalkulation.KalkulationsID_PK = dbo.Kalkulationsergebnis.KalkulationsID_FK
INNER JOIN
dbo.Maschine ON dbo.Kalkulation.MaschinenID_FK = dbo.Maschine.MaschinenID_PK
LEFT OUTER JOIN
dbo.Mitarbeiter AS Ersteller ON dbo.Kalkulation.Ersteller_MitarbeiterID_FK = Ersteller.MitarbeiterID_PK
LEFT OUTER JOIN
dbo.Mitarbeiter AS Bearbeiter ON dbo.Kalkulation.Bearbeiter_MitarbeiterID_FK = Bearbeiter.MitarbeiterID_PK
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm1 ON dbo.Kalkulation.KalkulationsID_PK = zm1.KalkulationsID_FK AND zm1.ZuschlagsID_FK = 1
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm2 ON dbo.Kalkulation.KalkulationsID_PK = zm2.KalkulationsID_FK AND zm2.ZuschlagsID_FK = 2
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm8 ON dbo.Kalkulation.KalkulationsID_PK = zm8.KalkulationsID_FK AND zm8.ZuschlagsID_FK = 8
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm4 ON dbo.Kalkulation.KalkulationsID_PK = zm4.KalkulationsID_FK AND zm4.ZuschlagsID_FK = 4
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm9 ON dbo.Kalkulation.KalkulationsID_PK = zm9.KalkulationsID_FK AND zm9.ZuschlagsID_FK = 9
有一种使用 FOR XML 连接值的技术,对于您的简单示例,它是这样的;
SELECT b.ID_Basis,
b.Name,
( SELECT case when m.FK = 1 then 'TEXT ' + m.note else m.note end + ','
FROM Mapping m
WHERE m.ID_Basis = b.ID_Basis
ORDER BY m.note
FOR XML PATH('') ) AS Notes
FROM Basis AS b
我试图将多个结果查询组合在一行中,但没有找到除以下方法之外的其他方法。但我对这个解决方案并不真正满意。有没有更优雅的解决方案?
情境一经典n:m映射
Table 1 - 基础
Table 1 个与此相似
| ID_Basis(PK) | Name |
|--------------|------|
| 1 | One |
| 2 | Two |
| 3 | Three|
Table 2 - 映射
| ID_Basis(FK) | ID_AddOn (FK) | note |
|--------------|---------------|---------|
| 1 | 1 | some |
| 1 | 2 | example |
| 5 | 1 | more |
| 5 | 3 | random |
| 5 | 4 | data |
Table 3 - 插件
在这个特定案例中,这个实际上不用于检索数据,但为了完整性而显示
| ID_AddOn(PK) | AddOn Name|
|--------------|-----------|
| 1 | something |
| 2 | extra |
| 3 | ... |
| 4 | ... |
目标
现在我想使用 table 2 从 table 1 检索所有数据(与 table 3 的所有给定插件连接)并将所有注释连接起来结果中的一个字段。
| ID_Basis | Note |
|--------------|--------------------|
| 1 | some, example |
| 3 | more, random, data |
我得出以下解决方案:
SELECT b.ID_Basis,
b.Name,
m1.note + m2.note + m3.note + m4.note
FROM Basis AS b
LEFT OUTER JOIN Mapping AS m1 ON b.ID_Basis = m1.ID_Basis AND m1.ID_Addon = 1
LEFT OUTER JOIN Mapping AS m2 ON b.ID_Basis = m2.ID_Basis AND m2.ID_Addon = 2
LEFT OUTER JOIN Mapping AS m3 ON b.ID_Basis = m3.ID_Basis AND m3.ID_Addon = 3
LEFT OUTER JOIN Mapping AS m4 ON b.ID_Basis = m4.ID_Basis AND m4.ID_Addon = 4
只要有新的插件,这个解决方案就会失败。像 group_concat
这样的东西在这里不是更好吗?但是 MS SQL 不支持。
附件 - 完整示例
SELECT
dbo.Kalkulation.KalkulationsID_PK,
dbo.Kalkulationseingaben.Format_Breite,
dbo.Kalkulationseingaben.Format_Hoehe,
dbo.Kalkulationseingaben.Auflage,
dbo.Kalkulation.MaschinenID_FK,
dbo.Kalkulation.Druckverfahrensbezeichnung_FK,
dbo.Kalkulationsergebnis.Einkaufspreis,
dbo.Kalkulation.Ersteller_MitarbeiterID_FK,
dbo.Kalkulation.Bearbeiter_MitarbeiterID_FK,
Ersteller.Nutzername AS Ersteller_Nutzername,
Bearbeiter.Nutzername AS Bearbeiter_Nutzername,
dbo.Kalkulation.Erstellungsdatum,
dbo.Kalkulation.Bearbeitungsdatum,
dbo.Kalkulationseingaben.Freitexthinweis,
dbo.Kalkulation.Kunden_KontaktID_FK,
dbo.Kalkulation.Kunden_Kurzbezeichnung,
dbo.Kalkulation.MaterialID_FK,
dbo.Kalkulationseingaben.Version,
dbo.Maschine.Maschinenbezeichnung + ' ' + dbo.Maschine.Firmenbezeichnung_FK AS Maschine,
CAST(CASE WHEN zm1.ZuschlagsID_FK = 1 THEN 'Farbe ' + '(' + zm1.Auswahl + ') ' ELSE '' END AS nvarchar)
+ CAST(CASE WHEN zm2.ZuschlagsID_FK = 2 THEN 'Lack ' ELSE '' END AS nvarchar)
+ CAST(CASE WHEN zm8.ZuschlagsID_FK = 8 THEN 'Rückseitendruck ' ELSE '' END AS nvarchar)
+ CAST(CASE WHEN zm4.ZuschlagsID_FK = 4 THEN 'Kaltprägung ' ELSE '' END AS nvarchar)
+ CAST(CASE WHEN zm9.ZuschlagsID_FK = 9 THEN 'Kleberabtötung' ELSE '' END AS nvarchar) AS Druckeinstellung
FROM
dbo.Kalkulation
INNER JOIN
dbo.Kalkulationseingaben ON dbo.Kalkulation.KalkulationsID_PK = dbo.Kalkulationseingaben.KalkulationsID_FK
INNER JOIN
dbo.Kalkulationsergebnis ON dbo.Kalkulation.KalkulationsID_PK = dbo.Kalkulationsergebnis.KalkulationsID_FK
INNER JOIN
dbo.Maschine ON dbo.Kalkulation.MaschinenID_FK = dbo.Maschine.MaschinenID_PK
LEFT OUTER JOIN
dbo.Mitarbeiter AS Ersteller ON dbo.Kalkulation.Ersteller_MitarbeiterID_FK = Ersteller.MitarbeiterID_PK
LEFT OUTER JOIN
dbo.Mitarbeiter AS Bearbeiter ON dbo.Kalkulation.Bearbeiter_MitarbeiterID_FK = Bearbeiter.MitarbeiterID_PK
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm1 ON dbo.Kalkulation.KalkulationsID_PK = zm1.KalkulationsID_FK AND zm1.ZuschlagsID_FK = 1
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm2 ON dbo.Kalkulation.KalkulationsID_PK = zm2.KalkulationsID_FK AND zm2.ZuschlagsID_FK = 2
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm8 ON dbo.Kalkulation.KalkulationsID_PK = zm8.KalkulationsID_FK AND zm8.ZuschlagsID_FK = 8
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm4 ON dbo.Kalkulation.KalkulationsID_PK = zm4.KalkulationsID_FK AND zm4.ZuschlagsID_FK = 4
LEFT OUTER JOIN
dbo.Kalkulation_Zuschlag_Map AS zm9 ON dbo.Kalkulation.KalkulationsID_PK = zm9.KalkulationsID_FK AND zm9.ZuschlagsID_FK = 9
有一种使用 FOR XML 连接值的技术,对于您的简单示例,它是这样的;
SELECT b.ID_Basis,
b.Name,
( SELECT case when m.FK = 1 then 'TEXT ' + m.note else m.note end + ','
FROM Mapping m
WHERE m.ID_Basis = b.ID_Basis
ORDER BY m.note
FOR XML PATH('') ) AS Notes
FROM Basis AS b