1

这让我困惑了几个小时。

所以我有一个活动表和一个供应商表。供应商可能有多个活动。如果供应商有足够的积分,我想选择所有广告系列。

问题是我不知道将从同一个供应商那里选择多少个广告系列,这意味着该供应商可能仍有两个广告系列的积分,但其余的则没有。

例子

tblvendors

+---------+------------+---------------+
|vendorId | vendorName | vendorCredits |
+---------+------------+---------------+
|    1    |      a     |      5        |
|    2    |      b     |      100      |
+---------+------------+---------------+

tblproducts

+-----------+---------------+------------+
| productId |  productName  |  vendorId  |
+-----------+---------------+------------+
|     1     |       c       |      1     |
|     2     |       e       |      2     |
|     3     |       f       |      1     |
|     4     |       g       |      1     |
|     5     |       h       |      1     |
+-----------+---------------+------------+

tblcampaigns

+------------+---------------+------------+
| campaignId |   productId   |  vendorId  |
+------------+---------------+------------+
|      1     |       1       |      1     |
|      2     |       2       |      2     |
|      3     |       3       |      1     |
|      4     |       4       |      1     |
|      5     |       5       |      1     |
+------------+---------------+------------+

现在考虑到每次选择一行时,供应商都会失去 2 个积分,因为供应商“a”只剩下 5 个积分,只有活动 1 2 和 3 应该返回。

我目前的查询是这样的:

SET @maxCampaignId = (SELECT MAX(campaignId) FROM tblCampaigns);
SELECT
    @maxCampaignId,
    t0.campaignId,
    t0.productId,
    productName,
    productDescription,
    productImage,
    (CASE WHEN campaignId > (SELECT configValue FROM tblconfiguration WHERE configKey = 'lastHomeCampaignId')
        THEN campaignId ELSE campaignId + @maxCampaignId END) AS orderField
FROM tblcampaigns AS t0
    INNER JOIN tblproducts AS t1 ON t0.productId = t1.productId
        INNER JOIN tblvendors AS t2 ON t1.vendorId = t2.vendorId
WHERE
    campaignType = 'homeFeature' AND
    t0.isActive = 1 AND
    t2.vendorCredits > (SELECT configValue FROM tblconfiguration WHERE configKey = 'campaignHomeFeatureCost' LIMIT 1)
ORDER BY orderField ASC
LIMIT 4

如您所见,问题在于比较 vendorCredits 的行。显然,查询选择的广告系列超出了供应商的承受能力。

我想避免在 PHP 中执行此操作,因为我认为应该可以直接从数据库中执行此操作。

4

2 回答 2

0

检查这篇文章,它可能会有所帮助 -group byhaving条款。我稍后会尝试做一些测试

在 WHERE 子句中使用 COUNT(*)

更新:

select t2.vendorId, vendorCredits from tblcampaigns AS t0 JOIN tblproducts AS t1 ON t0.productId = t1.productId JOIN tblvendors AS t2 ON t1.vendorId = t2.vendorId group by t2.vendorId having t2.vendorCredits = count(t2.vendorId)

如果我正确理解了这个问题:此查询将选择所有活动多于信用的供应商。

于 2012-10-24T12:15:51.587 回答
0

好的,找到了。

感谢这篇文章:如何限制 SQL 中每个字段值的行数?

我所做的是按照我想要的顺序选择我想要的行作为子查询及其各自的行号,以便我可以在最后重新排序它。

然后我创建了由 vendorId 排序的第二个子查询,以便我可以计算它出现的次数并将 row_count 返回到主查询。

最后,在主查询中,我将其重新排序为最深子查询中的行号,但现在我有了想要比较的值,即每行的信用值 * 特定供应商的当前行号。

无论如何,也许代码被清除了,这里是:

SET @creditsCost = (SELECT configValue FROM tblconfiguration WHERE configKey = 'campaignHomeFeatureCost' LIMIT 1);
SET @maxCampaignId = (SELECT MAX(campaignId) FROM tblCampaigns);
SET @curRow = 0;
SELECT * FROM
(
    SELECT *,
        @num := if(@first_column = vendorId, @num:= @num + 1, 1) as row_num,
        @first_column:=vendorId as c
    FROM
        (SELECT
            @curRow := @curRow + 1 AS row_number,
            @maxCampaignId,
            t0.campaignId,
            t0.productId,
            t2.vendorId,
            t2.vendorCredits,
            productName,
            productDescription,
            productImage,
            (CASE WHEN campaignId > (SELECT configValue FROM tblconfiguration WHERE configKey = 'lastHomeCampaignId')
                THEN campaignId ELSE campaignId + @maxCampaignId END) AS orderField
        FROM tblcampaigns AS t0
            INNER JOIN tblproducts AS t1 ON t0.productId = t1.productId
                INNER JOIN tblvendors AS t2 ON t1.vendorId = t2.vendorId
        WHERE
            campaignType = 'homeFeature' AND
            t0.isActive = 1
        ORDER BY orderField ASC) AS filteredCampaigns
    ORDER BY vendorId
) AS creditAllowedCampaigns
WHERE
    row_num * @creditsCost <= vendorCredits
ORDER BY row_number

无论如何,我仍然感谢谁花时间回答并尝试提供帮助,并将听取未来的评论,因为我认为这不是最好的表现方式。

于 2012-10-24T19:59:40.173 回答