请考虑以下表格。
CREATE TABLE asset (id INT PRIMARY KEY, ...other fields...);
CREATE TABLE property (id INT PRIMARY KEY, name TEXT, value INT);
CREATE TABLE asset_property (asset_id INT, property_id INT);
我希望选择资产并根据财产进行订购;但是,我希望将所有资产都包含在列表中,而不仅仅是那些具有我正在排序的属性的资产。例如,我可能有
INSERT INTO asset VALUES (1, ...);
INSERT INTO property VALUES (1, 'x', 50);
INSERT INTO property VALUES (2, 'y', 60);
INSERT INTO asset_property VALUES (1, 1);
INSERT INTO asset_property VALUES (1, 2);
INSERT INTO asset VALUES (2, ...);
INSERT INTO property VALUES (3, 'y', 70);
INSERT INTO asset_property VALUES (2, 3);
INSERT INTO asset VALUES (3, ...);
INSERT INTO property VALUES (4, 'x', 80);
INSERT INTO asset_property VALUES (3, 4);
INSERT INTO asset VALUES (4, ...);
我希望选择资产并按“x”属性进行排序。这对我来说听起来像是一个LEFT JOIN。
SELECT asset.* FROM asset
LEFT JOIN asset_property ON asset.id = asset_property.asset_id
LEFT JOIN property ON asset_property.asset_id = property.id
AND property.name = 'x'
ORDER BY property.value;
然而,精明的读者会注意到这会产生如下结果:
asset.id
1
3
1
2
4
资产1有两行,因为资产1具有名为“x”的属性,而另一行由于其具有未命名为“x”的属性而存在一行。
这是我的知识/理解不足的地方。为了回避这个问题,我尝试使用DISTINCT关键字。
SELECT DISTINCT asset.* FROM asset
LEFT JOIN asset_property ON asset.id = asset_property.asset_id
LEFT JOIN property ON asset_property.asset_id = property.id
AND property.name = 'x'
ORDER BY property.value;
这样做的问题在于,至少在SQLite(3.12.1)下,使用DISTINCT关键字似乎会覆盖ORDER BY子句:这些行按asset.id排序。
虽然我毫不怀疑这种数据库格式似乎是问题的根源,而不是我缺乏SQL魔法,但请保存你的能量,而不是建议我改变它;我知道该怎么做。虽然手头的任务可能不是 easy ,但我希望它是可能的,而且这种格式还有其它优点,可以让扭曲变得有价值。谢谢。
答案 0 :(得分:1)
如果只想使用property.name ='x'的行,则应使用内连接..
SELECT asset.* FROM asset
LEFT JOIN asset_property ON asset.id = asset_property.asset_id
INNER JOIN property ON asset_property.asset_id = property.id
AND property.name = 'x'
ORDER BY property.value;
或者你最后的评论
SELECT asset.* FROM asset
LEFT JOIN asset_property ON asset.id = asset_property.asset_id
INNER JOIN property ON asset_property.property_id = property.id
AND property.name = 'x'
ORDER BY case property.value when is null the 1 else 0 end, property.value;
答案 1 :(得分:0)
对您的测试数据进行一些假设,您应该能够使用更多的SQL语法来避免使用paste
:
a.addEventListener('keyup', hidebravo);
b.addEventListener('keyup', hidebravo);
子查询仅包含具有distinct
属性的行,然后主表左连接到该属性。这可以避免每select a.id
from asset a
left join (
select asset_id, value
from asset_property ap
left join property p on p.id=ap.property_id
where p.name = 'x'
) xp on a.id=xp.asset_id
order by case when xp.value is null then 1 else 0 end, xp.value
个多行,假设每个资产只能有零个或x
个属性。
答案 2 :(得分:0)
如果使用子选择怎么办:先选择distinct然后再订购?
Select * from (SELECT DISTINCT asset.*, property.value FROM asset LEFT JOIN asset_property ON asset.id = asset_property.asset_id LEFT JOIN property ON asset_property.asset_id = property.id AND property.name = 'x') ORDER BY property.value;
检查语法,只是试着解释一下这个方法。