选择在日期之间出现最少次数的记录

时间:2016-10-31 10:58:53

标签: mysql sql

我的表格列如下:

<li class="first-child">
    <a href="i.CityUrl">
        i.Name
    </a>
</li>

此表包含用户的银行详细信息历史记录。如果用户在我们的系统中更改其银行详细信息,则会在此表中插入一个新行。

我正在尝试创建一个查询,该查询将显示已在两个日期之间更改其详细信息的用户,并且可能在这些日期之间更改了一定次数。例如,显示已在| ID | UserID | AccountName | SortCode (encrypted) | AccountNumber (encrypted) | DateAdded 2016-01-01之间更改其详细信息的用户至少2次。

在两个日期之间进行选择是微不足道的,但我正在努力将#34;至少#times&#34;纳入其中。此外,每个用户的第一条记录不应包含在结果中,因为此记录是用户首次添加其银行详细信息(因此不会更改其银行详细信息)。

3 个答案:

答案 0 :(得分:3)

true

答案 1 :(得分:1)

先按用户分组,然后选择用户

SELECT * FROM Table t2
WHERE t2.UserId IN (
    SELECT t1.UserId
    FROM Table t1
    WHERE t1.DateAdded BETWEEN 'start_date' AND 'end_date'
    GROUP BY t1.UserId
    HAVING COUNT(*) >= 2
) AND t2.DateAdded BETWEEN 'start_date' AND 'end_date'
编辑(戈登):

我认为子查询回答了OP的问题:

    SELECT t1.UserId
    FROM Table t1
    WHERE t1.DateAdded BETWEEN $start_date AND $end_date
    GROUP BY t1.UserId
    HAVING COUNT(*) >= 2;

Niyoko的答案更进了一步,获得了原始的详细记录。

修改

我在最后一段中错过了要求。要排除每个用户的第一行,请使用以下SQL

SELECT t1.UserId
FROM Data t1
WHERE t1.DateAdded BETWEEN '2015-01-01' AND '2015-01-06'
AND t1.Id <> (SELECT Id FROM Data t2 WHERE t1.UserId = t2.UserId ORDER BY DateAdded LIMIT 1)
GROUP BY t1.UserId
HAVING COUNT(*) >= 2;

答案 2 :(得分:0)

使用提供的答案,我能够提出一个不需要对ID列进行排序的解决方案,并且在相当大的数据集中似乎非常有效。我最终使用的SQL是在下面。它确实创建了一些临时表,但似乎是我找到的最快的解决方案。我还要注意,这个SQL没有包含我需要的“最小出现次数”要求。我在PHP而不是SQL中实现了这个要求,因为SQL需要大量重复才能满足要求。

SELECT *
FROM UserBankDetails AS bd
LEFT JOIN (
    SELECT ID
    FROM UserBankDetails
    WHERE (UserID, DateAdded) IN (
        SELECT UserID, MIN(DateAdded)
        FROM UserBankDetails
        GROUP BY UserID
    )
) AS temp ON bd.ID = temp.ID
WHERE temp.ID IS NULL
AND bd.DateAdded BETWEEN '2015-01-01' AND '2015-12-01'
ORDER BY bd.UserID, bd.DateAdded

困难在于有效地排除了每个用户的最早记录。此解决方案为每个用户创建一个包含MIN DateAdded的临时表,然后使用left exclusion join从最终结果集中排除这些记录。

如上所述,我没有纳入“最低出现次数”要求,但是,这可以这样做(看看它有多详细):

SELECT *
FROM UserBankDetails AS bd
LEFT JOIN (
    SELECT ID
    FROM UserBankDetails
    WHERE (UserID, DateAdded) IN (
        SELECT UserID, MIN(DateAdded)
        FROM UserBankDetails
        GROUP BY UserID
    )
) AS temp ON bd.ID = temp.ID
WHERE temp.ID IS NULL
AND bd.DateAdded BETWEEN '2015-01-01' AND '2015-12-01'
AND bd.UserID IN (
    SELECT UserID
    FROM UserBankDetails AS bd1
    LEFT JOIN (
        SELECT ID
        FROM UserBankDetails
        WHERE (UserID, DateAdded) IN (
            SELECT UserID, MIN(DateAdded)
            FROM UserBankDetails
            GROUP BY UserID
        )
    ) AS temp1 ON bd1.ID = temp1.ID
    WHERE temp1.ID IS NULL
    AND bd1.DateAdded BETWEEN '2015-01-01' AND '2015-12-01'
    GROUP BY UserID
    HAVING COUNT(*) > 1
)
ORDER BY bd.UserID, bd.DateAdded