我正在重构非常旧的代码。目前,PHP为每个值生成一个单独的选择。说loc
包含1
,2
和data
包含a
,b
,它会生成
select val from tablename where loc_id=1 and data_id=a;
select val from tablename where loc_id=1 and data_id=b;
select val from tablename where loc_id=2 and data_id=a;
select val from tablename where loc_id=2 and data_id=b;
...等等都返回单个值或什么都不返回。这意味着我总是有n(loc_id)* n(data_id)结果,包括空值,这是后续处理所必需的。知道顺序,这用于生成HTML表。理论上,data_id和loc_id都可以扩展到几千(表中显然不是很好,但这是另一个问题)。
+-----------+-----------+
| data_id 1 | data_id 2 |
+----------+-----------+-----------+
| loc_id 1 | - | 999.99 |
+----------+-----------+-----------+
+ loc_id 2 | 888.88 | - |
+----------+-----------+-----------+
为了加快速度,我想用一个查询替换它:
select val from tablename where loc_id in (1,2) and data_id in (a,b) order by loc_id asc, data_id asc;
得到像(下面)的结果并迭代来构建我的表。
Rownum VAL
------- --------
1 null
2 999.99
3 777.77
4 null
不幸的是,这种方法会从结果集中删除空值,所以我最终得到了
Rownum VAL
------- --------
1 999.99
2 777.77
请注意,data_id或loc_id可能都没有匹配,在这种情况下我仍然需要null, null
。
所以我不知道哪个值匹配哪个。如果我添加loc_id和data_id,我可以在php中匹配预期的loc_id / data_id组合......但是这样会变得混乱。
一般来说仍然是SQL的新手,这绝对是我第一次使用PostgreSQL,所以希望这不太明显......当我发布这篇文章时,我正在寻找两种方法来解决这个问题:any in array[]
和join
秒。如果发现任何新内容,将更新。
我如何做where loc_id in (1,2) and data_id in (a,b)
并保留空值,以便我总是得到n(loc)* n(数据)结果?
答案 0 :(得分:1)
where (loc_id in (1,2) or loc_id is null)
and (data_id in (a,b) or data_id is null)
答案 1 :(得分:1)
您可以通过两个步骤在单个查询中实现此目的:
LEFT [OUTER] JOIN
到实际行。您的表格中的每个单元格都会至少一行
如果(loc_id, data_id)
是唯一的,则完全一行。
SELECT t.val
FROM (VALUES (1), (2)) AS l(loc_id)
CROSS JOIN (VALUES ('a'), ('b')) AS d(data_id) -- generate total grid of rows
LEFT JOIN tablname t USING (loc_id, data_id) -- attach matching rows (if any)
ORDER BY l.loc_id, d.data_id;
适用于任何列数>任何值的列。
对于你的简单案例:
SELECT t.val
FROM (
VALUES
(1, 'a'), (1, 'b')
, (2, 'a'), (2, 'b')
) AS ld (loc_id, data_id) -- total grid of rows
LEFT JOIN tablname t USING (loc_id, data_id) -- attach matching rows (if any)
ORDER BY ld.loc_id, ld.data_id;
答案 2 :(得分:0)
选择用于过滤的字段,以便了解值的来源:
select loc,data,val from tablename where loc in (1,2) and data in (a,b);
你也不会以这种方式获得null
,但它不再是问题了。您知道缺少哪些字段,并且您知道这些字段是null
。