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

Betinget SQL Query Assistance

Korte og enkle spørgsmål har en tendens til at få mere opmærksomhed end lange/komplekse. Det er ikke fordi vi ikke kan svare, men med så mange spørgsmål og så lidt frivillig tid at give, er det svært at retfærdiggøre tiden til at læse store spørgsmål.

Jeg tror dog, at dit grundlæggende krav ikke er så kompliceret. Du vil have en måde at hente rækker, der falder inden for et tidsinterval, ELLER, hvis de ikke er inden for det interval, angive de nærmeste rækker til dette interval.

I databaser, der understøtter ROW_NUMBER() OVER() er dette ret nemt (og MySQL 8.x er planlagt til at understøtte dette), men indtil det tidspunkt for at efterligne row_number() kan du bruge variabler og en ordnet underforespørgsel.

Du kan prøve denne løsning her på SQL Fiddle

MySQL 5.6 Schema Setup :

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

Forespørgsel :

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)
 

Så hvad dette gør, er at beregne et "RowNumber", som starter ved 1 for den seneste række for hver kildetabel. Derefter filtreres denne afledte tabel enten efter tidsintervallet eller efter rækkenummeret, hvis det ikke er inden for tidsintervallet.

Bemærk også, at jeg IKKE har brugt UNION men har i stedet brugt UNION ALL . Der er stor forskel på ydeevne og bør lære at bruge hver efter behov. Hvis du bruger UNION brug ikke også select distinct fordi du bare spilder kræfter.

Resultater :

| 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. Hvordan formindsker man temp tablespace i Oracle?

  2. SQL Server 2017:Import af CSV-data fra Linux til Salesforce med SSIS

  3. Hvordan opdaterer man en tabel automatisk, når en anden tabel opdateres på en anden mysql-server?

  4. Opret et forhold i SQL