1

少し悩んでいるのでアドバイスをお願いします。
私がしたいのは、tableB にエントリがある tableA からすべてを選択することです。ここで、tableB のエントリはテーブル内の最初のエントリであり、そのエントリは特定の日付範囲内にあります。

したがって、2013-01-01 00:00:00 の開始日と 2013-01-31 23:59:59 の終了日で、私はこのようなことをする必要があります

SELECT * FROM tblsites WHERE ID IN(SELECT 
IF(DateRequired >= '2013-01-01 00:00:00' AND DateRequired <= '2013-01-31 23:59:59', SiteID, '' ) AS SiteID FROM `tblmovements` WHERE TicketStatus IN ( 0, 1 ) GROUP BY SiteID) AND LENGTH(SiteName)>0 ORDER BY SiteName ASC

基本的に、選択した日付範囲内でそのサイトが最初に移動したサイト データのリストが返されます。DateRequired 列は tblmovements の移動日で、tblmovements は SiteID を列として格納します。チケットのステータスは無視できますが、チケットがアクティブであることを示す単なるフラグであり、クエリの結果はありません。

したがって、私の理論は、アクティブな tblmovements 内のすべてのチケットを選択し、それらを siteid でグループ化すると、DateRequired が入力日付の間にある場合にのみサブクエリがサイト ID を返すようにすることができ、それで実行できるようになるというものでした。サイト テーブルに対する単純な SELECT WHERE IN() 。LENGTH 句は、 if が else 句でゼロの長さを返すため、スクリプトでそれを除外するのではなく、クエリでそれらを除外したいためです。

クエリはエラーなしで実行されますが、地獄のように絶対に遅いです (30 分以上、まだ実行中です)。おそらく金曜の朝の憂鬱なだけですが、私を目覚めさせるための提案はありません。アップしていただければ幸いです。
上記の私のとりとめのないことを理解できれば、それを完全に記述するより良い方法でも問題ありません。

編集: ダミー テーブル。

--
-- Table structure for table `tblmovements`
--

CREATE TABLE IF NOT EXISTS `tblmovements` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `SiteID` bigint(20) unsigned NOT NULL,
  `TicketStatus` smallint(3) NOT NULL DEFAULT '1',
  `DateRequired` datetime DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `SiteID` (`SiteID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;

--
-- Dumping data for table `tblmovements`
--

INSERT INTO `tblmovements` (`ID`, `SiteID`, `TicketStatus`, `DateRequired`) VALUES
(1, 1, 1, '2013-01-02 00:00:00'),
(2, 1, 1, '2013-01-02 00:00:00'),
(3, 1, 1, '2013-02-02 00:00:00'),
(4, 1, 1, '2013-02-02 00:00:00'),
(5, 1, 1, '2013-02-02 00:00:00'),
(6, 2, 1, '2012-02-02 00:00:00'),
(7, 2, 1, '2012-02-02 00:00:00'),
(8, 2, 1, '2012-01-20 00:00:00'),
(9, 2, 1, '2013-01-02 00:00:00'),
(10, 2, 1, '2013-01-02 00:00:00');

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

--
-- Table structure for table `tblsites`
--

CREATE TABLE IF NOT EXISTS `tblsites` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `SiteName` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Dumping data for table `tblsites`
--

INSERT INTO `tblsites` (`ID`, `SiteName`) VALUES
(1, 'Site 1'),
(2, 'Site 2');

編集2:

スティーブの提案でOKです。クエリをこれに変更しました

SELECT tblmovements.SiteID, tblsites.SiteName FROM tblmovements
INNER JOIN tblsites
 ON tblmovements.SiteID = tblsites.ID
WHERE (tblmovements.TicketStatus = 0 OR tblmovements.TicketStatus = 1)
AND tblmovements.DateRequired>='2013-01-01 00:00:00' AND tblmovements.DateRequired<='2013-01-31 23:59:59'
GROUP BY tblmovements.SiteID

これは現在半作業中です。私が今抱えている問題は、その日付範囲の間にチケットがあるかどうかだけを選択していることです。ここで行う必要があるのは、tblmovements のエントリがそのテーブル内のそのサイト ID の最初の出現である場合にのみ、結果セットを返すことです。プライマリ クエリに戻ると、サブ セレクトに IF があることに気付くでしょう。

編集3

そうですね、スティーブの入力と金曜日以外の朝のバカの突然のひらめきに基づいて、私はそれをクラックしたと思います。

SELECT tblmovements.SiteID, tblsites.SiteName FROM tblmovements
INNER JOIN tblsites
 ON tblmovements.SiteID = tblsites.ID
WHERE (tblmovements.TicketStatus = 0 OR tblmovements.TicketStatus = 1)
AND tblmovements.DateRequired>='2013-01-01 00:00:00' AND tblmovements.DateRequired<='2013-01-31 23:59:59'
AND (SELECT COUNT(*) FROM tblmovements t3 WHERE t3.DateRequired<'2013-01-01 00:00:00' AND t3.SiteID=tblmovements.SiteID)<=0
GROUP BY tblmovements.SiteID

開始日の前にチケットの数を提供するための追加の条件を追加したので、理論的には、必要な日付の間にチケットがあり、開始日の前にチケットがないという結果セットが返された場合、返されるすべてのサイト ID は私が指定したものになるはずです。必要とする。

これまでのテストでは、期待どおりのデータ セットが返されており、クエリ実行時間は 0.5711 秒と著しく高速です。

4

1 に答える 1

2

サブクエリと IN リストではなく、ジョインはどうですか?

SELECT t1.SiteID, t2.* FROM tblmovements t1
WHERE (TicketStatus = 0 OR TicketStatus = 1)
AND t1.DateRequired BETWEEN '2013-01-01 00:00:00' AND '2013-01-31 23:59:59'
GROUP BY t1.SiteID)
INNER JOIN tblsites t2
 ON t1.SiteID = t2.ID

編集 1 - コメントへの返信:

ここで行ったことは、IF 評価を WHERE 条件ステートメントに移動することです。

元のクエリは、広範囲の行を選択し、それらを評価して SiteID または ''. where 条件で絞り込めるのに、なぜ大きな範囲を選択するのでしょうか。

于 2013-02-22T11:05:01.977 に答える