1

これは、数時間の検索で私を困惑させました。

したがって、キャンペーン テーブルとベンダー テーブルがあります。ベンダーはいくつかのキャンペーンを行っている場合があります。ベンダーに十分なクレジットがある場合は、すべてのキャンペーンを選択したいと考えています。

問題は、同じベンダーからいくつのキャンペーンが選択されるかわからないということです。つまり、ベンダーは 2 つのキャンペーンのクレジットをまだ持っていても、残りのキャンペーンのクレジットを持っていない可能性があります。

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 byおよびhaving条項。後でテストをしようと思います

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 で順序付けされた 2 番目のサブクエリを作成して、出現回数をカウントし、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 に答える