在简单的SQL JOIN中苦苦挣扎

时间:2013-06-27 18:20:46

标签: mysql sql join

我在SQL上非常糟糕,并且在使用两个表的UNIQUE连接时遇到了一些麻烦。 SQL结构有点糟糕,但我没有设计它。

我有两张桌子:

用户

uid,ufn,uln,ue

用户ID = uid。

交易

uid,unit,address,start_date

基本上在事务表中,每个uid有多个条目。我要做的是根据 ONLY 最新的start_date选择users.ufn, users.uln, users.ue, transactions.unit, transactions.address。意思是每个uid只会得到 ONE 结果。目前,我正在transactions表中获得所有 uid条目的退货。

我尝试过使用MAX做一些JOINS,LEFT JOINS和其他东西,但是基本上没有成功。

SELECT * FROM users JOIN ( SELECT unit, address, start_date FROM transactions GROUP BY uid) as a ON users.tenant_id = a.tenant_id

我尝试过的其他东西。

任何关于正确方向的提示都将非常感激。谢谢!

5 个答案:

答案 0 :(得分:7)

这会让你走近。问题是如果2个事务对同一个用户具有相同的开始日期。但如果你没有这种情况,这应该可以正常工作。

select u.ufn,
       u.uln,
       u.ue,
       t.unit,
       t.address
from   users u
inner join (
            select uid, 
                   max(start_date) as newest_start_date
            from transactions
            group by uid) x
on u.uid = x.uid
inner join transactions t
on t.start_Date = x.newest_start_date
and t.uid = u.uid

答案 1 :(得分:1)

您的示例SQL具有“tenant_id”,但这不在您的表示例中? 你每天运行一次还是10000次?

试试这个:

SELECT users.ufn, users.uln, users.ue, transactions.unit, transactions.address 
FROM users join transactions on users.uid = transactions.uid
WHERE transactions.UID, transactions.start_date IN
(SELECT UID, MAX(start_date) FROM TRANSACTIONS GROUP BY UID);

答案 2 :(得分:1)

另一个选择是在不等式上使用ANTI JOIN

select users.ufn,
       users.uln,
       users.ue,
       t.unit,
       t.address
from   users
INNER JOIN transactions t 
ON  t.uid = u.uid
LEFT JOIN transactions t1
ON t.uid = t1.uid
 and t.start_date < t1.start_date

WHERE
      t1.uid is null

由于t.start_date < t1.start_datet1.uid is null,只会选择没有其他具有更高start_date记录的记录

MAX()一样,如果两个或多个交易的start_dates与用户相关,那么您将获得两者

答案 3 :(得分:0)

此查询可以有效:

SELECT
   u.ufn,
   u.uln,
   u.ue,
   t2.unit,
   t2.address
FROM
    users AS u
INNER JOIN
    (
        SELECT
            uid
        ,   MAX(start_date) AS start_date
        FROM
            transactions
        WHERE
            uid = users.uid
    ) AS t1
INNER JOIN
    transaction AS t2 ON t2.uid = t1.uid AND t2.start_date = t1.start_date

临时表也是一个选项(可能更快,你必须尝试):

CREATE TEMPORARY TABLE
    last_transactions
AS SELECT
    uid
,   MAX(start_date) AS start_date
FROM
    transactions
GROUP BY
    uid
;
SELECT
    u.ufn,
    u.uln,
    u.ue,
    t2.unit,
    t2.address
FROM
    users AS u
INNER JOIN
    last_transactions AS t1 ON t1.uid = u.uid
INNER JOIN
    transaction AS t2 ON t2.uid = t1.uid AND t2.start_date = t1.start_date

P.S。:您绝对应该考虑在transactions表中添加主键。这样可以在t1t2之间建立更好的连接子句。此外,它还可以防止在同一用户发生多个start_date时可能发生的重复。

P.P.S。:不会在last_transaction_start_date表中添加user列更明智吗?

答案 4 :(得分:-1)

我不确定这是否与MySQL中的语法完全相同(很可能是),但是这里是你如何在SQL服务器中完成它。

使用rank()函数确定最新日期。

SELECT x。*,y。* 来自用户x 加入 (SELECT *,RANK()Over(按UID顺序分配Start_Date DESC)作为Rank_ FROM Transactions)为y ON x.uid = y.uid和y.rank_ = 1

希望这会有所帮助。

干杯!