web-dev-qa-db-ja.com

サブクエリを使用した最小値の選択

各マーチャントから最低価格を取得し、価格リンク(p_link)とマーチャント名+評価などの他の情報を出力するクエリを作成する必要があります。

価格のテーブル(tgmp_prices)、販売者のテーブル(tgmp_merchants)、アフィリエイト製品IDのテーブル(tgmp_affiliates)があります。

私は必要なすべての価格とデータを取得するクエリを既に取得しています。

SELECT p_id, p_m_id, p_prod_label, a_platform, p_link, p_price, m_title, m_link, m_avg_rating 
FROM tgmp_affiliates ga 
JOIN tgmp_prices p 
    ON ga.a_code = p.p_gtin 
        AND ga.a_code != '' 
JOIN tgmp_merchants m 
    ON m.m_id = p.p_m_id 
WHERE ga.site_id = '34' 
    AND p.site_id = '34' 
    AND ga.a_parent = '25573' 
    AND p_type = 'games' 
    AND m.m_hide = 0 
ORDER BY p.p_price ASC

販売者ID(p.p_m_idまたはm.m_id)で価格をグループ化し、各販売者の最低価格を選択するだけです。

SELECT p_id, p_m_id, p_prod_label, a_platform, p_link, p_price, m_title, m_link, m_avg_rating 
FROM tgmp_affiliates ga 
JOIN tgmp_prices p 
    ON ga.a_code = p.p_gtin 
        AND ga.a_code != '' 
JOIN tgmp_merchants m 
    ON m.m_id = p.p_m_id 
WHERE ga.site_id = '34' 
    AND p.site_id = '34' 
    AND ga.a_parent = '25573' 
    AND p_type = 'games' 
    AND m.m_hide = 0 
GROUP BY m.m_id
ORDER BY p.p_price ASC

ORDER BYの前にGROUP BY m.m_idを追加すると、16の結果が得られます。これを最低価格にするだけです。そこで、価格表(tgmp_prices)が次のように結合されているサブクエリを追加してみました。

SELECT p_id, p_m_id, p_prod_label, a_platform, p_link, p_price, m_title, m_link, m_avg_rating 
FROM tgmp_affiliates ga 
JOIN tgmp_prices p 
    ON ga.a_code = p.p_gtin 
        AND ga.a_code != '' 
        AND p.p_price = ( 
            SELECT MIN(p.p_price) 
            FROM tgmp_prices 
            WHERE p.p_m_id = m.m_id
        ) 
JOIN tgmp_merchants m 
    ON m.m_id = p.p_m_id 
WHERE ga.site_id = '34' 
    AND p.site_id = '34' 
    AND ga.a_parent = '25573' 
    AND p_type = 'games' 
    AND m.m_hide = 0 
GROUP BY m.m_id
ORDER BY p.p_price ASC

これは私に正しい結果を与えません-サブクエリが実行されるときにm.m_idが利用できないことが問題である可能性があると思うので、サブクエリ内でmerchantsテーブルに参加しようとしましたが、それでも終了します結果は同じです。

次のようなDDL:

CREATE TABLE IF NOT EXISTS `tgmp_affiliates` (
    `a_id` int(8) NOT NULL AUTO_INCREMENT,
    `site_id` int(6) NOT NULL,
    `a_parent` int(8) NOT NULL,
    `a_code` varchar(32) NOT NULL,
    `a_type` varchar(32) NOT NULL,
    `a_platform` varchar(12) NOT NULL,
    PRIMARY KEY (`a_id`),
    UNIQUE KEY `site_id` (`site_id`,`a_parent`,`a_code`,`a_type`,`a_platform`),
    KEY `a_code` (`a_code`),
    KEY `a_parent` (`a_parent`),
    KEY `a_platform` (`a_platform`),
    KEY `a_type` (`a_type`),
    KEY `site_id_2` (`site_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

-- --------------------------------------------------------

--
-- Table structure for table `tgmp_merchants`
--

CREATE TABLE IF NOT EXISTS `tgmp_merchants` (
    `m_id` int(8) NOT NULL AUTO_INCREMENT,
    `site_id` int(6) NOT NULL,
    `m_title` varchar(128) NOT NULL,
    `m_url` text NOT NULL,
    `m_link` varchar(128) NOT NULL,
    `m_favicon` text NOT NULL,
    `m_avg_rating` tinyint(1) NOT NULL,
    `m_hide` tinyint(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`m_id`),
    UNIQUE KEY `m_title` (`m_title`,`m_link`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

-- --------------------------------------------------------

--
-- Table structure for table `tgmp_prices`
--

CREATE TABLE IF NOT EXISTS `tgmp_prices` (
    `p_id` int(8) NOT NULL AUTO_INCREMENT,
    `site_id` int(6) NOT NULL,
    `p_m_id` int(8) NOT NULL,
    `p_prod_label` varchar(128) NOT NULL,
    `p_gtin` varchar(64) NOT NULL,
    `p_parent` int(8) NOT NULL,
    `p_link` text NOT NULL,
    `p_price` decimal(8,2) NOT NULL,
    `p_delivery` decimal(8,2) NOT NULL,
    `p_currencey` varchar(10) NOT NULL,
    `p_avail` varchar(32) NOT NULL,
    `p_condition` varchar(32) NOT NULL,
    `p_when` datetime NOT NULL,
    `p_type` varchar(32) NOT NULL,
    `p_hide` tinyint(1) NOT NULL DEFAULT '0',
    PRIMARY KEY (`p_id`),
    UNIQUE KEY `p_gtin` (`p_gtin`,`p_m_id`,`p_price`,`p_delivery`),
    KEY `p_price` (`p_price`),
    KEY `p_parent` (`p_parent`),
    KEY `site_id` (`site_id`),
    KEY `p_gtin_2` (`p_gtin`),
    KEY `p_type` (`p_type`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 ;

クエリを次のように修正しました。

SELECT p_id, p_m_id, p_prod_label, a_platform, p_link, p_price, m_title, m_link, m_avg_rating 
FROM tgmp_affiliates ga 
JOIN tgmp_prices p 
    ON ga.a_code = p.p_gtin 
        AND ga.a_code != '' 
        AND p.p_price = (
            SELECT MIN(tp.p_price) FROM tgmp_prices tp
                WHERE tp.p_m_id = m.m_id
                AND tp.p_parent = '25573'
    )
JOIN tgmp_merchants m 
    ON m.m_id = p.p_m_id 
WHERE ga.site_id = '34' 
    AND p.site_id = '34' 
    AND ga.a_parent = '25573' 
    AND p_type = 'games' 
    AND m.m_hide = 0 
GROUP BY m.m_id
ORDER BY p.p_price ASC

これにより正しい数の結果が得られ、それらは正しい結果セットに非常に近くなりますが、各マーチャントの最低価格を取得できていません。

3
James

2番目のクエリを少し変更すると、マーチャントIDと最低価格の両方が表示されます(条件を通過するすべての製品に対して-これがあなたの望みだと思います):

SELECT p.p_m_id, MIN(p_price) AS min_p_price 
FROM tgmp_affiliates ga 
JOIN tgmp_prices p 
    ON ga.a_code = p.p_gtin 
        AND ga.a_code > '' 
JOIN tgmp_merchants m 
    ON m.m_id = p.p_m_id 
WHERE ga.site_id = '34' 
    AND p.site_id = '34' 
    AND ga.a_parent = '25573' 
    AND p.p_type = 'games' 
    AND m.m_hide = 0 
GROUP BY p.p_m_id ;

次に、これを(派生テーブルとして)結果のデータが必要なすべてのテーブルに結合できます。

SELECT
    m.*, p.*, ga.*                     -- whatever columns you want  
FROM tgmp_affiliates ga 
JOIN tgmp_prices p 
    ON ga.a_code = p.p_gtin 
        AND ga.a_code > '' 
JOIN tgmp_merchants m 
    ON m.m_id = p.p_m_id 
JOIN
      ( SELECT p.p_m_id, MIN(p_price) AS p_price 
        FROM tgmp_affiliates ga 
        JOIN tgmp_prices p 
            ON ga.a_code = p.p_gtin 
                AND ga.a_code > '' 
        JOIN tgmp_merchants m 
            ON m.m_id = p.p_m_id 
        WHERE ga.site_id = '34' 
            AND p.site_id = '34' 
            AND ga.a_parent = '25573' 
            AND p.p_type = 'games' 
            AND m.m_hide = 0 
        GROUP BY p.p_m_id 
      ) AS tmp
    ON  tmp.p_m_id = p.p_m_id 
    AND tmp.p_price = p.p_price
WHERE ga.site_id = '34' 
    AND p.site_id = '34' 
    AND ga.a_parent = '25573' 
    AND p.p_type = 'games' 
ORDER BY p.p_price ;
1
ypercubeᵀᴹ