Mysql 重构多个左连接
我的表格布局的简化版本如下: 表项Mysql 重构多个左连接,mysql,Mysql,我的表格布局的简化版本如下: 表项 +----+-------+-----+ | ID | sdesc | ... | +----+-------+-----+ | 1 | item1 | ... | +----+-------+-----+ 表itemaffectTable(为具有数量的属性调用这些QPROP) TableItemAffectByTable(将这些BProp称为它们在出现时是相关的) 样本输出: itemID sdesc qpropID value
+----+-------+-----+
| ID | sdesc | ... |
+----+-------+-----+
| 1 | item1 | ... |
+----+-------+-----+
表itemaffectTable(为具有数量的属性调用这些QPROP)
TableItemAffectByTable(将这些BProp称为它们在出现时是相关的)
样本输出:
itemID sdesc qpropID value bpropID
1221 a copper lantern 4 2 5
1221 a copper lantern 18 2 5
1221 a copper lantern 17 -5 5
477 a shade 19 3 4
477 a shade 19 3 6
这在两方面是不正确的。对于第一项,affectbyID 5重复3次。。。这是可以容忍的。在第二种情况下,我们将affectID 19和affect值3重复两次,这是不允许的
理想情况下我想看看
itemID sdesc qpropID value bpropID
1221 a copper lantern 4 2 5
1221 a copper lantern 18 2 NULL
1221 a copper lantern 17 -5 NULL
477 a shade 19 3 4
477 a shade NULL NULL 6
主要问题是qpropIDs和值的重复,因为它们是相加的。如果解决方案重复bpropIDs,那没什么大不了的
**更新**
我试图使用完全连接的想法来获得结果,但似乎无法实现
最接近我想要的结果是使用SQLFIDLE获得
select i.id, i.sdesc, iaft.affectID, iaft.amount, NULL FROM item i
LEFT JOIN itemaffectTable iaft ON i.id=iaft.itemID
UNION
select i.id, i.sdesc, NULL, NULL, iafbt.affectbyID FROM item i
LEFT JOIN itemaffectedbyTable iafbt ON i.id=iafbt.itemID
ORDER BY id
所以最基本的想法是我想检索一个符合过滤器标准的项目列表,然后将这些项目与其关联的affectID和AffectById进行匹配
原文如下
SELECT DISTINCT i.id, i.sdesc, iaft.affectID, iaft.amount, iafbt.affectbyID FROM item i
INNER JOIN itemwearTable iwt ON i.id=iwt.itemID
LEFT JOIN itemaffectTable iaft ON i.id=iaft.itemID
LEFT JOIN itemaffectedbyTable iafbt ON i.id=iafbt.itemID
LEFT JOIN itemalignTable iat ON i.id = iat.itemID
LEFT JOIN itemgenderTable igt ON i.id = igt.itemID
LEFT JOIN itemgenreTable igrt ON i.id = igrt.itemID
LEFT JOIN itemclassTable ict ON i.id = ict.itemID
LEFT JOIN itemraceTable irt ON i.id = irt.itemID
WHERE (iat.itemID IS NULL OR iat.alignID = 1)
AND (igt.itemID IS NULL OR igt.genderID = 1)
AND (igrt.itemID IS NULL OR igrt.genreID = 1)
AND (ict.itemID IS NULL OR ict.classID = 1)
AND (irt.itemID IS NULL OR irt.raceID = 1)
AND i.minlvl <= 50
AND iwt.wearlocID=1
ORDER BY sdesc
从项目i中选择不同的i.id、i.sdesc、iaft.affectID、iaft.amount、iafbt.affectbyID
i.id上的内部联接项WearTable iwt=iwt.itemID
i.id上的左联接itemaffectTable iaft=iaft.itemID
i.id=iafbt.itemID上的LEFT JOIN itemaffectedbyTable iafbt
i.id上的左连接itemalignTable iat=iat.itemID
i.id=igt.itemID上的左连接项可转换igt
i.id=igrt.itemID上的左连接itemgeneretable igrt
i.id上的左联接itemclassTable ict=ict.itemID
i.id=irt.itemID上的左连接项RaceTable irt
其中(iat.itemID为NULL或iat.alignID=1)
和(igt.itemID为NULL或igt.genderID=1)
和(igrt.itemID为NULL或igrt.genreID=1)
和(ict.itemID为NULL或ict.classID=1)
和(irt.itemID为NULL或irt.raceID=1)
还有i.minlvl看看这里。我相信这就是你要找的。在SSMS中,我会用完全联接来解决这个问题,但显然在mysql中无法做到这一点,因此需要一个联合来组合左右外部联接
我不太明白你的预期结果。。。我觉得这很不合理
是否要对每个项目执行类似操作,假设分别获得item affect和item affectedBy,并希望以基于行的方式组合结果?i、 e.第一个结果中项目A的第1行将与第二个结果中项目A的第1行放在一起:例如
Item Affect Item AffectedBy
1 a 1 r
1 b
2 c 2 s
2 t
3 d
4 u
5 e 5 v
5 f 5 w
您希望看到以下内容:
Item Affect AffectedBy
1 a r
1 b NULL
2 c s
2 NULL t
3 d NULL
4 NULL u
5 e v
5 f w
select item_id, affect_id, rank() over (partition by item_id order by rownum) rank
from item_affect
order by item_id, rank;
对吧?
如果是这样的话,您可以想到的最直接的方法是,首先使项目影响的结果如下所示:
Item Affect seq
1 a 1
1 b 2
2 c 1
3 d 1
5 e 1
5 f 2
Seq列是项目组中的“等级”。
在受影响的项目中做类似的事情
然后对item和seq列进行完全外部联接
我不知道如何在MySQL中实现这些,在Oracle中,生成seq的方法如下:
Item Affect AffectedBy
1 a r
1 b NULL
2 c s
2 NULL t
3 d NULL
4 NULL u
5 e v
5 f w
select item_id, affect_id, rank() over (partition by item_id order by rownum) rank
from item_affect
order by item_id, rank;
试着想想你是否可以在MySQL中做类似的事情
对于完全外部联接,如果不支持,则始终可以使用左联接和右联接执行并集。这确实是一个奇怪的结果—它是一种旋转并集之类的
尽管如此,但它在这里,有你要求的所有钟声和口哨
select id, sdesc, affectID, amount, affectbyID
from (select
id, sdesc,
if(sameid and @affectID = affectID and @amount = amount, null, affectID) as affectID,
if(sameid and @affectID = affectID and @amount = amount, null, amount) as amount,
@affectID := affectID,
@amount := amount,
if(sameid and @affectbyID = affectbyID, null, affectbyID) as affectbyID,
@affectbyID := affectbyID
from (select
if(@id is null, false, @id = id) as sameId,
@id := id as id,
sdesc, affectID, amount, affectbyID
from (select distinct
i.id,
i.sdesc,
iaft.affectID,
iaft.amount,
iafbt.affectbyID
FROM item i
LEFT JOIN itemaffectTable iaft ON i.id=iaft.itemID
LEFT JOIN itemaffectedbyTable iafbt ON i.id=iafbt.itemID
ORDER BY 1,3,4,5
) x) y) z
这将使用来记住以前列的值
对于每个新的id
值,逻辑都会重置,如果列(或列对)的值与前一行的值相同,则其他列将变为null
请看a我正在努力理解你在说什么。也许一些示例数据和期望的输出会有所帮助。安会更好。@Bohemian我希望上面的编辑能澄清我的问题。谢谢!:)这个问题有一个赤裸裸的版本好吧,好吧,你把我累坏了!看到我的答案了吗?它做了你想要的一切(我希望!):)当我在我的完整数据集上使用它时,我看到弹出了几个错误的行,我添加了这些行。这似乎非常接近我想要的,比我提到的联合想法快了大约3倍。我添加了一个以前应该存在的orderby
,但是输出有什么问题?只是给我看小提琴没告诉我什么。我现在就开始gtg——我会寻找你的额外反馈,看看我能在大约12小时内做些什么。我看到了我的实时数据和sqfiddle之间的差异。我在一个新的sqfiddle中添加了一个“问题”项,您的查询处理得非常好。当我在live server上运行查询时,会得到旧的、不正确的结果,就好像IF语句没有执行一样。这可能是GoDaddy的配置问题或版本问题。此外,将DISTINCT添加到第一个select处理了最初引起我注意的重复项。