左连接表有多个条件

时间:2013-02-15 09:06:23

标签: mysql join

我正在努力解决一个问题。我需要LEFT JOIN两个特定id匹配的表和日期不同的表:

SELECT
    *
FROM
    u_data ud
JOIN
    u_contracts uc
ON
    uc.user_id = ud.id
LEFT JOIN
    u_transactions ut
ON
    ut.contract_id = uc.id
    /* AND DATE( ut.add_timestamp ) > DATE( ud.suspicious ) */
WHERE
    ud.suspicious > 0
    AND ud.suspicious != ''
    AND ud.suspicious IS NOT NULL
    AND uc._status = 6
GROUP BY
    ud.id;

这给了我正确的行数,但我还需要检查,如果事务日期大于第一个表中的可疑日期。一旦我添加了这个条件(在开始的地方尝试过),它就会删除所有没有交易日期的字段。

意思是,如果我LEFT JOIN这些表,我会得到这样的结果:

+-----+----------+---------------+---------------+--------+
| row | original | ud.suspicious | add_timestamp | amount |
+-----+----------+---------------+---------------+--------+
|   1 |      100 | 10.01.2000    | 01.01.2000    |     50 |
|   2 |      100 | 10.01.2000    | NULL          | NULL   |
|   3 |      100 | 10.01.2000    | 12.01.2000    |     10 |
|   4 |      100 | 11.01.2000    | 12.01.2000    |     20 |
|   5 |      100 | 12.01.2000    | 12.01.2000    |     30 |
+-----+----------+---------------+---------------+--------+

现在,我基本上需要消除01.01.2000的金额和日期,因为它比可疑日期早了,我不需要额外的金额,但我需要原件虽然。这就是我需要的东西

+-----+----------+---------------+---------------+--------+
| row | original | ud.suspicious | add_timestamp | amount |
+-----+----------+---------------+---------------+--------+
|   1 |      100 | 10.01.2000    | NULL          | NULL   |
|   2 |      100 | 10.01.2000    | NULL          | NULL   |
|   3 |      100 | 10.01.2000    | 12.01.2000    |     10 |
|   4 |      100 | 11.01.2000    | 12.01.2000    |     20 |
|   5 |      100 | 12.01.2000    | 12.01.2000    |     30 |
+-----+----------+---------------+---------------+--------+

但是,当我设定条件DATE( ut.add_timestamp ) > DATE( ud.suspicious )时,我得到了这个:

+-----+----------+---------------+---------------+--------+
| row | original | ud.suspicious | add_timestamp | amount |
+-----+----------+---------------+---------------+--------+
|   1 |      100 | 10.01.2000    | 12.01.2000    |     10 |
|   2 |      100 | 11.01.2000    | 12.01.2000    |     20 |
|   3 |      100 | 12.01.2000    | 12.01.2000    |     30 |
+-----+----------+---------------+---------------+--------+

为什么要删除LEFT JOIN条目,如何解决此问题以获取所需的正确数据?


修改 完整的原始工作查询:

SELECT
    ud.Pcode AS pcode
    , CONCAT( ud.Name, ' ', ud.Surname ) AS name
    , CONCAT(
        ud.Da_CityName,
        IF ( ud.Da_Street != '', CONCAT( ', ', ud.Da_Street ), '' ),
        IF ( ud.Da_Housen != '', CONCAT( ', ', ud.Da_Housen ), '' ),
        IF ( ud.Da_Flatn != '', CONCAT( ', ', ud.Da_Flatn ), '' ),
        IF ( ud.Da_PostIndex != '', CONCAT( ', ', ud.Da_PostIndex ), '' )
    ) AS address
    , uc.id AS contract_id
    , uc.terminate_date AS terminate_date
    , FORMAT( IF ( (
        SELECT
            SUM( external_account )
        FROM
            u_transactions
        WHERE
            contract_id = uc.id 
            AND nulled = 0
            AND type in ( 'penalty', 'initial', 'comission', 'penalty2', 'penalty2_vat' )
            AND DATE( add_timestamp ) > DATE( ud.suspicious )
    ) IS NULL, uc.inkasso_debt, uc.inkasso_debt - (
        SELECT
            SUM( external_account )
        FROM
            u_transactions
        WHERE
            contract_id = uc.id 
            AND nulled = 0
            AND type in ( 'penalty', 'initial', 'comission', 'penalty2', 'penalty2_vat' )
            AND DATE( add_timestamp ) > DATE( ud.suspicious )
    ) ), 2 ) AS summ
FROM
    u_data ud
JOIN
    u_contracts uc
ON
    uc.user_id = ud.id
WHERE
    ud.suspicious > 0
    AND ud.suspicious != ''
    AND ud.suspicious IS NOT NULL
    AND uc._status = 6
    AND DATE( uc.terminate_date ) < ( NOW() - INTERVAL 45 DAY )

因为它太乱了,我试图摆脱两个子选择并加入它们以获得SUM( external_account )数量。也许这有助于理解我的问题。

4 个答案:

答案 0 :(得分:1)

尝试:

SELECT
    row, original, ud.suspicious, isnull(u_transaction, '') as u_transaction, isnull(amount, '')
FROM
    u_data ud
JOIN
    u_contracts uc
ON
    uc.user_id = ud.id
LEFT JOIN
    u_transactions ut
ON
    ut.contract_id = uc.id
    AND DATE( ut.add_timestamp ) > DATE( ud.suspicious )
WHERE
    ud.suspicious > 0
    AND ud.suspicious != ''
    AND ud.suspicious IS NOT NULL
    AND uc._status = 6
GROUP BY
    ud.id;

不确定它是否会起作用,没时间尝试,但我记得遇到过类似的问题并且解决了类似问题。

答案 1 :(得分:1)

我认为它在u_transaction和amount中给出了NULL,因为你正在使用AND和ON 条件,尝试将其放在where子句中,看看会发生什么。

试试这个

SELECT
    *
FROM
    u_data ud
JOIN
    u_contracts uc
ON
    uc.user_id = ud.id
LEFT JOIN
    u_transactions ut
ON
    ut.contract_id = uc.id

WHERE
    ud.suspicious > 0
    AND ud.suspicious != ''
    AND ud.suspicious IS NOT NULL
    AND uc._status = 6
    AND DATE( ut.add_timestamp ) > DATE( ud.suspicious )
GROUP BY
    ud.id;

答案 2 :(得分:1)

尝试

...
RIGHT JOIN u_transactions ut
ON ut.contract_id = uc.id
AND ( DATE( ut.add_timestamp ) > DATE( ud.suspicious )
      OR ut.add_timestamp IS NULL )
...
查询中的

答案 3 :(得分:0)

如果您需要的是输出中的NULL字符串,请在select语句中添加IF语句。

SELECT
  IF(
     DATE( ut.add_timestamp ) < DATE( ud.suspicious ),
     'NULL',
     ud.add_timestamp
    ) AS add_timestamp
FROM
  -----Rest of the query-----

根据您更新的帖子,以下是我的查询版本。如果您可以在sqlfiddle.com中创建表结构,如果此查询无法解决您的问题,那将非常有用。

SELECT  

  FORMAT(
     IF(                
            SUM(external_account) IS NULL,                                  
            uc.inkasso_debt,
            uc.inkasso_debt -  SUM( external_account)
    ), 2) AS summ

FROM
    u_data ud
    JOIN u_contracts uc ON uc.user_id = ud.id
    LEFT JOIN u_transactions ON (   
                               u_transactions.contract_id = uc.id                                                                        
                               AND nulled = 0                                                                          
                               AND (type in ( 'penalty', 'initial', 'comission', 'penalty2', 'penalty2_vat' ))
                               AND DATE(u_transactions.add_timestamp ) > DATE( ud.suspicious )                                                                  
                            )                                                                     


WHERE
  ud.suspicious > 0   
  AND uc._status = 6
  AND DATE( uc.terminate_date ) < ( NOW() - INTERVAL 45 DAY )

GROUP BY
  ud.id