SQL JOIN查询未返回预期结果

时间:2014-04-10 20:21:35

标签: mysql sql join

2我知道我有一个简单的问题..但我不能为我的生活解决它..这就是我尝试做的事情。我有3个表和一些示例数据:

customer_entity_varchar

  entity_id    attribute_id        value

   '2'             '5'             'John'
   '2'             '7'             'Smith'
   '2'             '336'           'ADELANTO'
   '3'             '5'             'Jane'
   '3'             '7'             'Doe'
   '3'             '336'           'ADELANTO'
   '4'             '5'             'Peter'
   '4'             '7'             'Griffin'
   '4'             '336'           'Not ADELANTO'

customer_entity

  entity_id        email 

   '2'             'jsmith@whatever.com'
   '3'             'janed@thisthat.com'
   '4'             'peterg@notanemail.com'

我想为first name某个地区的所有人匹配last nameemailattribut_id = '336'。我正在尝试的是:

SELECT CE.email as email,
    max(case when CEV.attribute_id = '5' then CEV.value end) as FirstName,
    max(case when CEV.attribute_id = '7' then CEV.value end) as LastName
FROM customer_entity_varchar CEV
LEFT JOIN customer_entity CE
ON ( CE.entity_id = CEV.entity_id)
WHERE CEV.value ='ADELANTO'
AND CEV.attribute_id='336'

我对结果的希望是:

           email                    FirstName             LastName

    jsmith@whatever.com               John                  Smith
    janed@thisthat.com                Jane                  Doe

然而,我要回的是一行 - email有一个值,但FirstNameLastName都是空白。我的逻辑有缺陷吗?

4 个答案:

答案 0 :(得分:0)

我可能会这样解决这个问题。它是一种有利于可读性的解决方案。

WITH firstNames AS
(SELECT entity_id, Value FROM customer_entity_char WHERE attribute_id = '5')
lastNames AS
(SELECT entity_id, Value FROM customer_entity_char WHERE attribute_id = '7')
districts AS
(SELECT entity_id, Value FROM customer_entity_char WHERE attribute_id = '336')
SELECT ce.email, fn.Value, ln.Value, d.Value FROM firstNames fn,lastNames ln, districts d
INNER JOIN customer_entity ce
WHERE fn.entity_id = ln.entity_id AND ln.entity_id = d.entity_id AND ce.entity_id = d.entity_id
AND d.Value = 'ADELANTO';

答案 1 :(得分:0)

首先,你真的在​​你的所有价值观上都有这些刻度吗?换句话说,引用存储在数据库中吗?  正如一些民众所指出的那样,这种数据库设计真的很难查询。

基本上,您必须通过customer_entity_varchar表进行两次传递。一个通道是为你感兴趣的人获取entity_id(在我的查询中别名为T1),一个获取他们的属性(在查询中为cev)。您将针对t1查询过滤此“adelanto”值,该查询将为您提供entity_ids。然后,您可以将其加入CEV别名,以获取所需的实际信息。 (希望所有这些都有意义)。

我认为这就是你要找的东西:

SQL Fiddle

SELECT  CE.email as email,
max(case when CEV.attribute_id = '5' then CEV.value end) as FirstName,
    max(case when CEV.attribute_id = '7' then CEV.value end) as LastName
FROM customer_entity_varchar CEV
inner join (select distinct entity_id, value from customer_entity_varchar where attribute_id = 336) t1
  on t1.entity_id = cev.entity_id
LEFT JOIN customer_entity CE
ON ( CE.entity_id = CEV.entity_id)
and t1.value = 'ADELANTO'
group by
ce.entity_id
编辑:正如MPelletier所指出的那样,你需要包括一个组。我不能忍受MySQL会允许你在没有它的情况下提交该查询。

答案 2 :(得分:0)

查询中的WHERE条件是使用attribute_id 5,7排除行,因此它不会给出包含名和姓的值。

试试这个

SELECT CE.email as email,
    max(case when CEV.attribute_id = '5' then CEV.value end) as FirstName,
    max(case when CEV.attribute_id = '7' then CEV.value end) as LastName

FROM
 ( 
 SELECT entity_id,attribute_id,value
 FROM customer_entity_varchar
 WHERE entity_id IN (
                     SELECT entity_id 
                     FROM customer_entity_varchar
                     WHERE value ='ADELANTO'
                     AND attribute_id='336'
                    )
 AND attribute_id IN ('5','7')
 )As CEV
INNER JOIN customer_entity CE
ON CE.entity_id = CEV.entity_id
GROUP BY CEV.entity_id

SQL Fiddle Demo

答案 3 :(得分:0)

您正在处理实体属性值表。这意味着你将在每个查询中遭受无数个外连接的乐趣。这就是为什么EAV 糟透了而且你被告知不要这样做,除非你必须这样做。

单个查询修复:

SELECT DISTINCT
--  ^^^^You need this because you're cross joining the crap out of the EAV table.
    CEV.entity_id,
    CE.email,
    CEV5.value "FirstName",
    CEV7.value "LastName"
FROM customer_entity_varchar CEV
--  ^^^^ This is the base table that determines what entities exist.  It makes sure you always have your entity_id even if attributes are missing.
LEFT JOIN customer_entity_varchar CEV5
    ON CEV5.entity_id = CEV.entity_id AND CEV5.attribute_id = 5
--  ^^^^ This is the join that lets you access attribute 5, FirstName
LEFT JOIN customer_entity_varchar CEV7
    ON CEV7.entity_id = CEV.entity_id AND CEV7.attribute_id = 7
--  ^^^^ This is the join that lets you access attribute 7, LastName
LEFT JOIN customer_entity_varchar CEV336
    ON CEV336.entity_id = CEV.entity_id AND CEV336.attribute_id = 336
--  ^^^^ This is the join that lets you access attribute 336, City?
LEFT JOIN customer_entity CE
    ON CE.entity_id = CEV.entity_id
--  ^^^^ Here's the other table, joined to the base table so we're sure it joins when partial data exists.
WHERE CEV336.value = 'ADELANTO'

以下是如何更轻松地完成这项工作。

首先,查看您的EAV表:

CREATE VIEW vw_customer_entity_varchar AS
SELECT DISTINCT
    CEV.entity_id
    CEV5.value "FirstName",
    CEV7.value "LastName",
    CEV336.value "City?"
FROM customer_entity_varchar CEV
LEFT JOIN customer_entity_varchar CEV5
    ON CEV5.entity_id = CEV.entity_id AND CEV5.attribute_id = 5
LEFT JOIN customer_entity_varchar CEV7
    ON CEV7.entity_id = CEV.entity_id AND CEV7.attribute_id = 7
LEFT JOIN customer_entity_varchar CEV336
    ON CEV336.entity_id = CEV.entity_id AND CEV336.attribute_id = 336

在您的EAV表格中为每个字段添加其他联接。

然后,您可以将此视图视为普通表,但性能很差,并且不能将其用于INSERTUPDATEDELETE

欢迎来到EAV地狱。

相关问题