英文:
What's a clean way to join tables with Entity-Attribute-Value?
问题
我在想我是否以最有效的方式进行操作。
我有一个数据库表,其中包含自定义数据元素。要查看哪些记录使用自定义对象表中的数据,我必须连接三个ID号,以及指定描述。这并不是太糟糕,但有时我的SQL脚本中可能有多达30个这样的连接,这可能会很冗长。我想知道是否有更清晰的编码方式?也许可以使用临时存储过程或临时函数吗?
SELECT
r.ID,
apples.status,
oranges.status,
bananas.status
FROM
record r
LEFT JOIN
custom_object apples ON apples.T_ID1 = r.T_ID1
AND apples.T_ID2 = r.T_ID2
AND apples.T_ID3 = r.T_ID3
AND apples.DESC = 'Apples'
LEFT JOIN
custom_object oranges ON oranges.ID1= r.T_ID1
AND oranges.T_ID2 = r.T_ID2
AND oranges.T_ID3 = r.T_ID3
AND oranges.DESC = 'Oranges'
LEFT JOIN
custom_object bananas ON bananas.T_ID1= r.T_ID1
AND bananas.T_ID2 = r.T_ID2
AND bananas.T_ID3 = r.T_ID3
AND bananas.DESC = 'Bananas'
英文:
I am wondering if I'm doing this in the most efficient way possible.
I have a database table that houses custom data elements. To see what records use the data in the custom object table I have to join on 3 ID numbers, as well as specify the description. It's not that bad, but sometimes I can have up to 30 of these joins in my SQL script and that can be long. I was wondering if there is a cleaner way to code this? Maybe with a temp stored procedure or temp function?
SELECT
r.ID,
apples.status,
oranges.status,
bananas.status
FROM
record r
LEFT JOIN
custom_object apples ON apples.T_ID1 = r.T_ID1
AND apples.T_ID2 = r.T_ID2
AND apples.T_ID3 = r.T_ID3
AND apples.DESC = 'Apples'
LEFT JOIN
custom_object oranges ON oranges .ID1= r.T_ID1
AND oranges.T_ID2 = r.T_ID2
AND oranges.T_ID3 = r.T_ID3
AND oranges.DESC = 'Oranges'
LEFT JOIN
custom_object bananas ON bananas.T_ID1= r.T_ID1
AND bananas.T_ID2 = r.T_ID2
AND bananas.T_ID3 = r.T_ID3
AND bananas.DESC = 'Bananas'
答案1
得分: 1
使用带有案例表达式的单个连接在这里似乎是一个更简单的方法。
SELECT
r.ID,
AppleStatus = CASE WHEN co.[DESC] = '苹果' THEN co.status END,
OrangeStatus = CASE WHEN co.[DESC] = '橙子' THEN co.status END,
BananaStatus = CASE WHEN co.[DESC] = '香蕉' THEN co.status END
FROM record r
LEFT JOIN custom_object co ON co.T_ID1 = r.T_ID1
AND co.T_ID2 = r.T_ID2
AND co.T_ID3 = r.T_ID3
AND co.[DESC] IN ('苹果', '橙子', '香蕉')
英文:
Using a single join with a case expression seems like a much simpler approach here.
SELECT
r.ID,
AppleStatus = case when co.[DESC] = 'Apples' then co.status end,
OrangeStatus = case when co.[DESC]= 'Oranges' then co.status end,
BananaStatus = case when co.[DESC] = 'Bananas' then co.status end
FROM record r
LEFT JOIN custom_object co ON co.T_ID1 = r.T_ID1
AND co.T_ID2 = r.T_ID2
AND co.T_ID3 = r.T_ID3
AND co.[DESC] in ('Apples', 'Oanges', 'Bananas')
答案2
得分: 1
条件聚合是可能的:
SELECT
r.ID,
MAX(CASE WHEN co.[DESC] = 'Apples' THEN co.status END) AS applesStatus,
MAX(CASE WHEN co.[DESC] = 'Oranges' THEN co.status END) AS orangesStatus,
MAX(CASE WHEN co.[DESC] = 'Bananas' THEN co.status END) AS bananasStatus
FROM
record r
LEFT JOIN
custom_object co ON co.T_ID1 = r.T_ID1
AND co.T_ID2 = r.T_ID2
AND co.T_ID3 = r.T_ID3
AND co.[DESC] IN ('Apples', 'Oranges', 'Bananas') -- optional
GROUP BY r.ID
在 OUTER APPLY
中执行相同的操作将避免外部的 GROUP BY
并在构建查询的其余部分时提供更多的灵活性:
SELECT
r.ID,
statuses.*
FROM
record r
OUTER APPLY (
SELECT
MAX(CASE WHEN co.[DESC] = 'Apples' THEN co.status END) AS applesStatus,
MAX(CASE WHEN co.[DESC] = 'Oranges' THEN co.status END) AS orangesStatus,
MAX(CASE WHEN co.[DESC] = 'Bananas' THEN co.status END) AS bananasStatus
FROM custom_object co
WHERE co.T_ID1 = r.T_ID1
AND co.T_ID2 = r.T_ID2
AND co.T_ID3 = r.T_ID3
AND co.[DESC] IN ('Apples', 'Oranges', 'Bananas') -- optional
) statuses
还可以使用公共表达式(CTE):
; WITH statuses AS (
SELECT
co.T_ID1, co.T_ID2, co.T_ID3,
MAX(CASE WHEN co.[DESC] = 'Apples' THEN co.status END) AS applesStatus,
MAX(CASE WHEN co.[DESC] = 'Oranges' THEN co.status END) AS orangesStatus,
MAX(CASE WHEN co.[DESC] = 'Bananas' THEN co.status END) AS bananasStatus
FROM custom_object co
WHERE co.[DESC] IN ('Apples', 'Oranges', 'Bananas') -- optional
GROUP BY co.T_ID1, co.T_ID2, co.T_ID3
)
SELECT
r.ID,
s.applesStatus,
s.orangesStatus,
s.bananasStatus
FROM
record r
LEFT JOIN
statuses s ON s.T_ID1 = r.T_ID1
AND s.T_ID2 = r.T_ID2
AND s.T_ID3 = r.T_ID3
以上所有的操作都假设在相同的ID组合下没有重复的属性。
为了获得最佳性能,您应该在 custom_object(T_ID1, T_ID2, T_ID3, [DESC])
上定义一个索引。
示例结果:
ID | applesStatus | orangesStatus | bananasStatus |
---|---|---|---|
1 | Apples1 | Oranges1 | Bananas1 |
2 | Apples2 | null | null |
3 | null | Oranges3 | null |
4 | null | null | Bananas4 |
5 | null | null | null |
6 | Apples6 | null | Bananas6 |
查看此 db<>fiddle。
英文:
Conditional aggregation is a possibility:
SELECT
r.ID,
MAX(CASE WHEN co.[DESC] = 'Apples' THEN co.status END) AS applesStatus,
MAX(CASE WHEN co.[DESC] = 'Oranges' THEN co.status END) AS orangesStatus,
MAX(CASE WHEN co.[DESC] = 'Bananas' THEN co.status END) AS bananasStatus
FROM
record r
LEFT JOIN
custom_object co ON co.T_ID1 = r.T_ID1
AND co.T_ID2 = r.T_ID2
AND co.T_ID3 = r.T_ID3
AND co.[DESC] IN ('Apples', 'Oranges', 'Bananas') -- optional
GROUP BY r.ID
The same inside an OUTER APPLY
will avoid the outer GROUP BY
and allow more flexibility as you build out the rest of your query.
SELECT
r.ID,
statuses.*
FROM
record r
OUTER APPLY (
SELECT
MAX(CASE WHEN co.[DESC] = 'Apples' THEN co.status END) AS applesStatus,
MAX(CASE WHEN co.[DESC] = 'Oranges' THEN co.status END) AS orangesStatus,
MAX(CASE WHEN co.[DESC] = 'Bananas' THEN co.status END) AS bananasStatus
FROM custom_object co
WHERE co.T_ID1 = r.T_ID1
AND co.T_ID2 = r.T_ID2
AND co.T_ID3 = r.T_ID3
AND co.[DESC] IN ('Apples', 'Oranges', 'Bananas') -- optional
) statuses
A Common Table Expression (CTE) can also be used:
; WITH statuses AS (
SELECT
co.T_ID1, co.T_ID2, co.T_ID3,
MAX(CASE WHEN co.[DESC] = 'Apples' THEN co.status END) AS applesStatus,
MAX(CASE WHEN co.[DESC] = 'Oranges' THEN co.status END) AS orangesStatus,
MAX(CASE WHEN co.[DESC] = 'Bananas' THEN co.status END) AS bananasStatus
FROM custom_object co
WHERE co.[DESC] IN ('Apples', 'Oranges', 'Bananas') -- optional
GROUP BY co.T_ID1, co.T_ID2, co.T_ID3
)
SELECT
r.ID,
s.applesStatus,
s.orangesStatus,
s.bananasStatus
FROM
record r
LEFT JOIN
statuses s ON s.T_ID1 = r.T_ID1
AND s.T_ID2 = r.T_ID2
AND s.T_ID3 = r.T_ID3
The above all assume no duplicate properties per ID combination.
For best performance, you should define an index on custom_object(T_ID1, T_ID2, T_ID3, [DESC])
.
Sample results:
ID | applesStatus | orangesStatus | bananasStatus |
---|---|---|---|
1 | Apples1 | Oranges1 | Bananas1 |
2 | Apples2 | null | null |
3 | null | Oranges3 | null |
4 | null | null | Bananas4 |
5 | null | null | null |
6 | Apples6 | null | Bananas6 |
See this db<>fiddle.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论