sql >> データベース >  >> RDS >> Mysql

条件付きSQLクエリ支援

    短くて単純な質問は、長くて複雑な質問よりも注目を集める傾向があります。これは、答えられないからではなく、質問が非常に多く、ボランティアの時間がほとんどないため、大きな質問を読む時間を正当化するのは困難です。

    ただし、基本的な要件はそれほど複雑ではないと思います。時間範囲内にある行を取得する方法、またはその範囲内にない場合はその範囲に最も近い行を提供する方法が必要です。

    ROW_NUMBER()OVER()をサポートするデータベースでは、これは非常に簡単です(MySQL 8.xはこれをサポートする予定です)が、それまでは、row_number()をエミュレートするために、変数と順序付きサブクエリを使用できます。

    このソリューションは、 SQLFiddle で試すことができます。

    MySQL5.6スキーマのセットアップ

    CREATE TABLE `ponumber` (
      `TimeStr` datetime NOT NULL,
      `Value` int(11) NOT NULL,
      UNIQUE KEY `uk_Times` (`TimeStr`));
    
    INSERT INTO `PONumber`     (`TimeStr`,`Value`) VALUES ('2017-09-28 10:47:55',0);
    INSERT INTO `PONumber`     (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:07',1217911);
    INSERT INTO `PONumber`     (`TimeStr`,`Value`) VALUES ('2017-09-28 05:24:18',1217906);
    
    CREATE TABLE `batch_number` (
      `TimeStr` datetime NOT NULL,
      `Value` int(11) NOT NULL,
      UNIQUE KEY `uk_Times` (`TimeStr`));
    
    INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:46:18',5522);
    INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 12:25:33',5521);
    INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-29 11:44:45',5520);
    INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:05',5519);
    INSERT INTO `batch_number` (`TimeStr`,`Value`) VALUES ('2017-09-28 05:22:58',5518);
    
    CREATE TABLE `batchweight` (
      `TimeStr` datetime NOT NULL,
      `Value` int(11) NOT NULL,
      UNIQUE KEY `uk_Times` (`TimeStr`));
    
    INSERT INTO `batchweight`  (`TimeStr`,`Value`) VALUES ('2017-09-29 12:46:19',38985);
    INSERT INTO `batchweight`  (`TimeStr`,`Value`) VALUES ('2017-09-28 06:26:07',38985);
    INSERT INTO `batchweight`  (`TimeStr`,`Value`) VALUES ('2017-09-28 05:23:03',31002);
    

    クエリ

    SET @bStartTime  := '2017-09-29 11:10:00'   
    SET @bEndTime    := '2017-09-29 12:48:00'
    
    SELECT 
          SrcTable, TimeStr, Value
    FROM (
          SELECT
                @row_num :=IF( @prev_value=u.SrcTable, @row_num + 1 ,1) AS RowNumber
              , u.*
              , @prev_value := u.SrcTable
          FROM (
    
              select 'ponumber' SrcTable , TimeStr, `Value`
              from ponumber
              union all
              select 'batch_number' SrcTable , TimeStr, `Value`
              from batch_number
              union all
              select 'batchweight' SrcTable , TimeStr, `Value`
              from batchweight
              ) u
          CROSS JOIN (SELECT @row_num := 1,  @prev_value :='') vars
          ORDER BY SrcTable, TimeStr DESC
          ) d
    WHERE (d.TimeStr between @bStartTime and @bEndTime)
       OR (TimeStr < @bStartTime AND RowNumber = 1)
    

    したがって、これは、各ソーステーブルの最新の行に対して1から始まる「RowNumber」を計算します。次に、この派生テーブルは、時間範囲、または時間範囲内にない場合は行番号のいずれかでフィルタリングされます。

    また、未使用であることに注意してください UNION 代わりにUNION ALLを使用しました 。パフォーマンスには大きな違いがあり、必要に応じてそれぞれの使い方を学ぶ必要があります。 UNIONを使用する場合 select distinctも使用しないでください 努力を無駄にしているだけだからです。

    結果

    |     SrcTable |              TimeStr | Value |
    |--------------|----------------------|-------|
    |  batchweight | 2017-09-29T12:46:19Z | 38985 |
    | batch_number | 2017-09-29T12:46:18Z |  5522 |
    | batch_number | 2017-09-29T12:25:33Z |  5521 |
    | batch_number | 2017-09-29T11:44:45Z |  5520 |
    |     ponumber | 2017-09-28T10:47:55Z |     0 |
    



    1. 特定の日付の一意のリピーターごとに1日あたりの顧客数を取得するにはどうすればよいですか?

    2. JDBCを使用してMySQLにselectを挿入します

    3. OracleApplicationExpressでのSQL入門

    4. テーブルPHPエコーでの発生をカウント