XML 上的 DISTINCT 与 CAST
DISTINCT on XML with CAST
我有 4 个 table。 table 不包含任何 foreign key
引用,其中名称的类型为 xml
t1:
| id | name |
+-----+----------------+
| a1 | <ID>a1<ID> |
| a2 | <ID>a2<ID> |
| a3 | <ID>a3<ID> |
t2:
| id | name | t1_id |
+-----+-------------+--------------+
| b1 | <ID>b1<ID> | a1 |
| b2 | <ID>b2<ID> | a2 |
| b3 | <ID>b3<ID> | a3 |
| b4 | <ID>b4<ID> | a1 |
t3:
| id | name | t2_id |
+-----+-------------+--------------+
| c1 | <ID>c1<ID> | b1 |
| c2 | <ID>c2<ID> | b2 |
| c3 | <ID>c3<ID> | b3 |
t4:
| id | name | t3_id |
+-----+-------------+--------------+
| d1 | <ID>d1<ID> | c2 |
| d2 | <ID>d2<ID> | c3 |
我需要获取所有相关数据。
当我指定 'a1' 时,我期望的是
| name | name | name | name |
+--------------+-------------+--------------+--------------+
| <ID>a1<ID> | <ID>b1<ID> | <ID>c1<ID> | |
| | <ID>b4<ID> | | |
得到的结果:
| name | name | name | name |
+--------------+-------------+--------------+--------------+
| <ID>a1<ID> | <ID>b1<ID> | <ID>c1<ID> | |
| <ID>a1<ID> | <ID>b4<ID> | | |
为了解决这个问题,我使用了
SELECT DISTINCT CAST (a.name AS TEXT), CAST (b.name AS TEXT), CAST (c.name AS TEXT), CAST (d.name AS TEXT)
FROM t1 AS a
LEFT JOIN t2 AS b
ON b.id =
CAST((xpath('/ID/text()', b.name))[1] AS TEXT)
LEFT JOIN t3 AS c
ON c.id =
CAST((xpath('/ID/text()', c.name))[1] AS TEXT)
LEFT JOIN t4 AS d
ON d.id =
CAST((xpath('/ID/text()', d.name))[1] AS TEXT)
以上方法无效。如何解决这个问题。这是优化查询吗?我试过嵌套查询。 Distinct
问题也出现在那里
实现此目标的最佳优化方法是什么?使用 JOIN
或 Nested query
?
您显示的查询与 table 示例中的逻辑不匹配。这将:
SELECT t1.name::text, t2.name::text, t3.name::text, t4.name::text
FROM t1
LEFT JOIN t2 b ON t2.t1_id = t1.id
LEFT JOIN t3 c ON t3.t2_id = t2.id
LEFT JOIN t4 d ON t4.t3_id = t3.id
WHERE t1.id = 'a1';
而且您的问题中没有任何内容可以保证使用 DISTINCT
。
如果您真的想在显示的有序列表的同一列中隐藏重复的名称:
SELECT CASE WHEN rn1 = 1 THEN name1 END AS name1
, CASE WHEN rn2 = 1 THEN name2 END AS name2
, CASE WHEN rn3 = 1 THEN name3 END AS name3
, CASE WHEN rn4 = 1 THEN name4 END AS name4
FROM (
SELECT t1.name::text AS name1, t2.name::text AS name2, t3.name::text AS name3, t4.name::text AS name4
, row_number() OVER (PARTITION BY t1.id ORDER ORDER BY t2.id, t3.id, t4.id) AS rn1
, row_number() OVER (PARTITION BY t1.id, t2.id ORDER ORDER BY t3.id, t4.id) AS rn2
, row_number() OVER (PARTITION BY t1.id, t2.id, t3.id ORDER ORDER BY t4.id) AS rn3
FROM t1
LEFT JOIN t2 b ON t2.t1_id = t1.id
LEFT JOIN t3 c ON t3.t2_id = t2.id
LEFT JOIN t4 d ON t4.t3_id = t3.id
WHERE t1.id = 'a1'
) sub
ORDER BY t1.id, t2.id, t3.id, t4.id;
我有 4 个 table。 table 不包含任何 foreign key
引用,其中名称的类型为 xml
t1:
| id | name |
+-----+----------------+
| a1 | <ID>a1<ID> |
| a2 | <ID>a2<ID> |
| a3 | <ID>a3<ID> |
t2:
| id | name | t1_id |
+-----+-------------+--------------+
| b1 | <ID>b1<ID> | a1 |
| b2 | <ID>b2<ID> | a2 |
| b3 | <ID>b3<ID> | a3 |
| b4 | <ID>b4<ID> | a1 |
t3:
| id | name | t2_id |
+-----+-------------+--------------+
| c1 | <ID>c1<ID> | b1 |
| c2 | <ID>c2<ID> | b2 |
| c3 | <ID>c3<ID> | b3 |
t4:
| id | name | t3_id |
+-----+-------------+--------------+
| d1 | <ID>d1<ID> | c2 |
| d2 | <ID>d2<ID> | c3 |
我需要获取所有相关数据。 当我指定 'a1' 时,我期望的是
| name | name | name | name |
+--------------+-------------+--------------+--------------+
| <ID>a1<ID> | <ID>b1<ID> | <ID>c1<ID> | |
| | <ID>b4<ID> | | |
得到的结果:
| name | name | name | name |
+--------------+-------------+--------------+--------------+
| <ID>a1<ID> | <ID>b1<ID> | <ID>c1<ID> | |
| <ID>a1<ID> | <ID>b4<ID> | | |
为了解决这个问题,我使用了
SELECT DISTINCT CAST (a.name AS TEXT), CAST (b.name AS TEXT), CAST (c.name AS TEXT), CAST (d.name AS TEXT)
FROM t1 AS a
LEFT JOIN t2 AS b
ON b.id =
CAST((xpath('/ID/text()', b.name))[1] AS TEXT)
LEFT JOIN t3 AS c
ON c.id =
CAST((xpath('/ID/text()', c.name))[1] AS TEXT)
LEFT JOIN t4 AS d
ON d.id =
CAST((xpath('/ID/text()', d.name))[1] AS TEXT)
以上方法无效。如何解决这个问题。这是优化查询吗?我试过嵌套查询。 Distinct
问题也出现在那里
实现此目标的最佳优化方法是什么?使用 JOIN
或 Nested query
?
您显示的查询与 table 示例中的逻辑不匹配。这将:
SELECT t1.name::text, t2.name::text, t3.name::text, t4.name::text
FROM t1
LEFT JOIN t2 b ON t2.t1_id = t1.id
LEFT JOIN t3 c ON t3.t2_id = t2.id
LEFT JOIN t4 d ON t4.t3_id = t3.id
WHERE t1.id = 'a1';
而且您的问题中没有任何内容可以保证使用 DISTINCT
。
如果您真的想在显示的有序列表的同一列中隐藏重复的名称:
SELECT CASE WHEN rn1 = 1 THEN name1 END AS name1
, CASE WHEN rn2 = 1 THEN name2 END AS name2
, CASE WHEN rn3 = 1 THEN name3 END AS name3
, CASE WHEN rn4 = 1 THEN name4 END AS name4
FROM (
SELECT t1.name::text AS name1, t2.name::text AS name2, t3.name::text AS name3, t4.name::text AS name4
, row_number() OVER (PARTITION BY t1.id ORDER ORDER BY t2.id, t3.id, t4.id) AS rn1
, row_number() OVER (PARTITION BY t1.id, t2.id ORDER ORDER BY t3.id, t4.id) AS rn2
, row_number() OVER (PARTITION BY t1.id, t2.id, t3.id ORDER ORDER BY t4.id) AS rn3
FROM t1
LEFT JOIN t2 b ON t2.t1_id = t1.id
LEFT JOIN t3 c ON t3.t2_id = t2.id
LEFT JOIN t4 d ON t4.t3_id = t3.id
WHERE t1.id = 'a1'
) sub
ORDER BY t1.id, t2.id, t3.id, t4.id;