Mysql
 sql >> Database >  >> RDS >> Mysql

Assistenza per le query SQL condizionali

Le domande brevi e semplici tendono ad attirare più attenzione di quelle lunghe/complesse. Questo non perché non possiamo rispondere, ma con così tante domande e così poco tempo da dedicare volontario, è difficile giustificare il tempo per leggere grandi domande.

Tuttavia penso che il tuo requisito di base non sia così complesso. Vuoi un modo per recuperare le righe che rientrano in un intervallo di tempo O, se non in quell'intervallo, fornire le righe più vicine a quell'intervallo.

Nei database che supportano ROW_NUMBER() OVER() questo è abbastanza semplice (e MySQL 8.x è pianificato per supportarlo), ma fino a quel momento per emulare row_number() puoi usare variabili e una sottoquery ordinata.

Puoi provare questa soluzione qui su SQL Fiddle

Impostazione dello schema MySQL 5.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);

Interroga :

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)

Quindi, ciò che fa è calcolare un "RowNumber" che inizia da 1 per la riga più recente per ciascuna tabella di origine. Quindi questa tabella derivata viene filtrata in base all'intervallo di tempo o al numero di riga se non all'interno dell'intervallo di tempo.

Tieni inoltre presente che NON utilizzato UNION ma invece hanno usato UNION ALL . C'è una grande differenza nelle prestazioni e dovresti imparare a usarle in base alle necessità. Se si utilizza UNION non usare anche select distinct perché stai solo sprecando fatica.

Risultati :

|     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 |