0

次のように定義された2つのテーブルがあります。

CREATE TABLE `product` (
`pid` SMALLINT( 5 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR( 50 ) NOT NULL,
`description` TEXT,
`qty` SMALLINT( 5 ) UNSIGNED NOT NULL DEFAULT '0',
`category` ENUM( '1', '2', '3', '4', '5', '6', '7', '8' ) NOT NULL DEFAULT '1',
`price` DECIMAL( 7, 2 ) UNSIGNED NOT NULL
) ENGINE = InnoDB;

CREATE TABLE `discount` (
`did` SMALLINT( 5 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`pid` SMALLINT( 5 ) UNSIGNED NOT NULL,
`sDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`eDate` DATETIME NOT NULL,
`dPrice` DECIMAL( 7, 2 ) UNSIGNED NOT NULL,
FOREIGN KEY ( `pid` ) REFERENCES `product`(`pid`)
    ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB;

すべての製品に対して正確に 1 行の結果を取得しようとしていNULLます。sDate < NOW()eDate > NOW()

私は試した:

select p.pid, name, price, dPrice, qty
from product p left join discount d
on p.pid = d.pid
where d.sDate<now() and d.eDate>now();

これに関する問題は、有効な割引のある製品のみが返されることです。割引なし、期限切れ・将来割引の商品は表示されません。

次に試しました:

select p.pid, name, price, dPrice, qty
from product p left join discount d
on p.pid = d.pid
where (d.sDate<now() and d.eDate>now()) or dPrice is null;

これは、有効な割引のある製品と割引のない製品をリストするという私の望ましい結果に一歩近づきましたが、期限切れ/将来の割引が定義されている製品がまだありません.

常に 1 つの割引のみがアクティブであることの確認は PHP で行われるため、このステートメントに含める必要はありません。どんな助けでも大歓迎です!

4

4 に答える 4

4
select p.pid, name, price, dPrice, qty
from product p 

left join discount d on p.pid = d.pid and d.sDate<now() and d.eDate>now()

サブクエリよりも効率的で「標準的」です。

于 2009-12-10T22:18:15.210 に答える
2

どうですか

SELECT p.name, d.dPrice
FROM   product p LEFT JOIN discount d
ON     p.pid = d.pid AND now() BETWEEN d.sDate AND d.eDate
于 2009-12-10T22:18:26.673 に答える
1

おそらく、サブクエリが のフィルター処理されたバージョンを返し、discountその後 で結合したままにできるようにする必要がありますproduct

select p.pid, name, price, dPrice, qty
from product p left join
(select * from discount where sDate<now() and eDate>now()) d
on p.pid = d.pid;

(ここで SQL 構文にわずかなエラーがあるかもしれませんが、アイデアはわかります:WHERE句を 1 つのテーブルにのみ適用する必要があるため、サブクエリでそのテーブルに適用し、結果データ セットを結合する代わりに、最初にテーブルを結合してからフィルタリングします。)

于 2009-12-10T22:15:18.260 に答える
0

それがまさにOuter Joinsが発明された目的です。

select p.*,d.dPrice from product p left outer join discount d on p.pid=d.pid and now() between d.sDate and d.eDate

left joinfull の代わりに省略形を使用できますleft outer join。ただし、通常の内部結合ではなく、外部結合であることを覚えておくとよいでしょう。

于 2009-12-10T23:46:54.017 に答える