«SELECT» қалай және алдыңғы жолдардан бос жолдарды дайындау керек?

SELECT * FROM кестесінен ORDER BY төмендегі (оңайлатылған) нәтиже бар, оны белгілеңіз :

tick refid value
----------------
1    1     11
1    2     22
1    3     33
2    1     1111
2    3     3333
3    3     333333

1-жаңарту үшін «жетіспейтін» жолдарға назар аударыңыз (3-құсбелгіні қойыңыз) және 2-тиін (2 және 3-кенелер)

Мүмкін болса, сол refid үшін ең соңғы мәні арқылы бұл жетіспейтін жолдарды қосу үшін сұрауды қалай жасауға болады? «Ең соңғы» деген жол жетіспейтін жол сияқты бірдей жолға арналған мәнді және жетпейтін жолдың белгісінен аз екенін көрсететін үлкен белгілеуді білдіреді. мысалы,

tick refid value
----------------
1    1     11
1    2     22
1    3     33
2    1     1111
2    2     22
2    3     3333
3    1     1111
3    2     22
3    3     333333

Қосымша шарттар:

  • Барлық өрістерде tick = 1 кезінде мәндер болады.
  • Бірнеше рет «жоғалтылған» кенелерді жүйеге келтіру үшін (жоғарыда келтірілген 2-дегідей)
  • болуы мүмкін.
  • Көптеген утилиталар бар және қай жерде сирек мәлімет болатыны белгісіз.
  • 3-тен кейінгі көптеген кенелер болады, бірақ барлық дәйекті. Дұрыс нәтиже берсеңіз, әр арна әрбір таңба үшін нәтиже береді.
  • Өткізілмеген жолдар алдын-ала белгілі емес - бұл бірдей құрылыммен және әртүрлі «жоқ» жолдармен бірнеше дерекқорларда іске қосылады.

Мен MySQL-ды пайдаланып жатырмын және db-ді қазір ғана өзгерте алмаймын. Басқа диалектте жауап беруді талқылауға көмектесуге тырысыңыз, бірақ мен MySQL диалектісінде басқалардан жауапты таңдаймын.

Ия, мен мұны іске асырған кодта жасалатынын білемін. Мен SQL-мен жасалса, мен жай ғана қызықтырамын.

4
«Ең соңғы» деген сөзбен бірге value жолында refid деген жолда мәні дегенді білдіреді және tick code> tick - бұл <<<<> Толықтай болмайтын (яғни, кестеде мүлдем орын алмайтын) tick бар ма және оны қосу керек пе?
қосылды автор outis, көзі
@estis «ең соңғы» мәні анықтауға дұрыс. tick файлының жоқтығына сенімдімін (бірақ оны жабайы көрген емеспін)
қосылды автор Chadwick, көзі

4 жауаптар

Берілген белгілеу тіркесімі болмаған кезде қандай value қайтарылуы керек? Бұл шешімде, мен осы жеңілдік үшін ең төменгі мәнді қайтардым.

Тексеру

Нөлдік жағдайда қандай мәнді пайдалануға болатындығын анықтау үшін логиканы жаңарттым. Кестелерде кенелер + қолдауы бірегей екендігін ескеру керек.

Select Ticks.tick
    , Refs.refid
    , Case
        When Table.value Is Null 
            Then    (
                    Select T2.value
                    From Table As T2
                    Where T2.refid = Refs.refId
                        And T2.tick =  (
                                        Select Max(T1.tick)
                                        From Table As T1
                                        Where T1.tick < Ticks.tick
                                            And T1.refid = T2.refid
                                        )
                    )
        Else Table.value
        End As value
From    (
        Select Distinct refid
        From Table
        ) As Refs
    Cross Join  (
                Select Distinct tick
                From Table
                ) As Ticks
    Left Join Table
        On Table.tick = Ticks.tick
            And Table.refid = Refs.refid
3
қосылды
EXPLAIN негізінде, бұл сұрау қазіргі уақытта орналастырылғандардың ең жақсы нәтижесіне ие.
қосылды автор outis, көзі
@Chadwick - Мысалы, мен 743 белгісінде жұмыс істеп жатырмын және 32-ші жаңартуды жоғалтпаймын. Енді 732-нің идентификаторы 32-ке арналған құндылыққа ие болады және 744-нің 32-ні жаңарту үшін мән бар. Мысалы, 740-нен бастап қолданамын ба?
қосылды автор Thomas, көзі
@Chadwick - Сонымен қатар, осы кестеде бір бүтін бастапқы кілт бар ма?
қосылды автор Thomas, көзі
@Chadwick - Ok. Содан кейін менің түзетілген шешіміммен шабуыл жасау керек деп ойлаймын
қосылды автор Thomas, көзі
Жетіспейтін жолдарға енгізілген мән ең соңғы болуы тиіс (тапсырыс берілген шикізаттар негізінде), сол үшін көрсетілген. Refid = 1 мысалын қараңыз.
қосылды автор Chadwick, көзі
бұл сценарийде 743 белгісімен, 32-ші өрісті 740, емес 744 белгілеуімен бірдей мән берілетін болады.
қосылды автор Chadwick, көзі
иә, int бастапқы кілті бар
қосылды автор Chadwick, көзі

Төменде менің дәмім үшін тым көп қосалқы таңбалар бар, бірақ MySQL-де қажетті нәтиже жасайды, әр кесте және әрқайсысы үстелде кемінде бір рет бөлек болғанша.

Әрбір жұпты жасайтын және жақсартатын сұрауды бастаңыз. Келесі кесте жұптарды генерациялау үшін пайдаланады, сондықтан негізгі кестеде қандай да бір белгілеу ешқашан пайда болмаса, ол жасалынған жұптардан да болмайды. Сонымен қатар, «refick = 1» деген барлық шектеулерді «ешбір жағдайда ешқашан болмайды» деп шектеу керек.

SELECT tick, refid FROM
  (SELECT refid FROM chadwick WHERE tick=1) AS r
  JOIN 
  (SELECT DISTINCT tick FROM chadwick) AS t

Using this, generate every missing tick, refid pair, along with the largest tick that exists in the table by equijoining on refid and θ-joining on tick. Group by the generated tick, refid since only one row for each pair is desired. The key to filtering out existing tick, refid pairs is the HAVING clause. Strictly speaking, you can leave out the HAVING; the resulting query will return existing rows with their existing values.

SELECT tr.tick, tr.refid, MAX(c.tick) AS ctick
  FROM 
      (SELECT tick, refid FROM
        (SELECT refid FROM chadwick WHERE tick=1) AS r
        JOIN 
        (SELECT DISTINCT tick FROM chadwick) AS t
      ) AS tr
  JOIN chadwick AS c ON tr.tick >= c.tick AND tr.refid=c.refid
  GROUP BY tr.tick, tr.refid
  HAVING tr.tick > MAX(c.tick)

Жоғарыда көрсетілгеннен бір түпнұсқалық таңдау, түпнұсқалық кестеге қосылып, берілген кестеге мәнді алу үшін кестеге жаңа жолдарды қайтарады.

INSERT INTO chadwick
SELECT missing.tick, missing.refid, c.value
  FROM (SELECT tr.tick, tr.refid, MAX(c.tick) AS ctick
    FROM 
      (SELECT tick, refid FROM
        (SELECT refid FROM chadwick WHERE tick=1) AS r
        JOIN 
        (SELECT DISTINCT tick FROM chadwick) AS t
      ) AS tr
    JOIN chadwick AS c ON tr.tick >= c.tick AND tr.refid=c.refid
    GROUP BY tr.tick, tr.refid
  ) AS missing
  JOIN chadwick AS c ON missing.ctick = c.tick AND missing.refid=c.refid
;

(белгілеу, қолдана отырып) және (refid, tick) индекстерімен бірге үлгілік кестедегі өнімділік:

+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+
| id | select_type | table      | type  | possible_keys     | key      | key_len | ref      | rows | Extra                           |
+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+
|  1 | PRIMARY     |  | ALL   | NULL              | NULL     | NULL    | NULL     |    3 |                                 |
|  1 | PRIMARY     | c          | ALL   | tick_ref,ref_tick | NULL     | NULL    | NULL     |    6 | Using where; Using join buffer  |
|  2 | DERIVED     |  | ALL   | NULL              | NULL     | NULL    | NULL     |    9 | Using temporary; Using filesort |
|  2 | DERIVED     | c          | ref   | tick_ref,ref_tick | ref_tick | 5       | tr.refid |    1 | Using where; Using index        |
|  3 | DERIVED     |  | ALL   | NULL              | NULL     | NULL    | NULL     |    3 |                                 |
|  3 | DERIVED     |  | ALL   | NULL              | NULL     | NULL    | NULL     |    3 | Using join buffer               |
|  5 | DERIVED     | chadwick   | index | NULL              | tick_ref | 10      | NULL     |    6 | Using index                     |
|  4 | DERIVED     | chadwick   | ref   | tick_ref          | tick_ref | 5       |          |    2 | Using where; Using index        |
+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+

Мен айтқанымдай, тым көп субпункттар бар. Уақытша кесте сұрақтарға көмектесуі мүмкін.

Жетіспеген кенелерді тексеру үшін:

SELECT clo.tick+1 AS missing_tick
  FROM chadwick AS chi
    RIGHT JOIN chadwick AS clo ON chi.tick = clo.tick+1
  WHERE chi.tick IS NULL;

Бұл кем дегенде бір жолды кестеде ең үлкен белгі 1 + тең деп белгілейді. Осылайша, осы нәтижедегі ең үлкен мән еленбейді.

0
қосылды

Толық тізім алу үшін жұптардың тізімін (белгілеу, бекіту) жасау үшін:

     SELECT a.tick, b.refid
       FROM ( SELECT DISTINCT tick  FROM t) a
 CROSS JOIN ( SELECT DISTINCT refid FROM t) b

Енді осы сұранымнан алынған рефераттар:

     SELECT a.tick tick, b.refid refid
       FROM ( SELECT DISTINCT tick  FROM t) a
 CROSS JOIN ( SELECT DISTINCT refid FROM t) b
 MINUS
     SELECT DISTINCT tick, refid FROM t

Енді соңғы сұрауды алу үшін t-пен қосыла аласыз (алдыңғы нәтижені алу үшін ішкі қосылысты + сол жақ қосылуды қолданыңыз, бірақ бейімделе аласыз):

INSERT INTO t(tick, refid, value)
SELECT c.tick, c.refid, t1.value
  FROM (        SELECT a.tick tick, b.refid refid
                  FROM ( SELECT DISTINCT tick  FROM t) a
            CROSS JOIN ( SELECT DISTINCT refid FROM t) b
            MINUS
                SELECT DISTINCT tick, refid FROM t
       ) c
 INNER JOIN t t1 ON t1.refid = c.refid and t1.tick < c.tick
  LEFT JOIN t t2 ON t2.refid = c.refid AND t1.tick < t2.tick AND t2.tick < c.tick
 WHERE t2.tick IS NULL 
0
қосылды
Бұл тәсіл басқа RDBMS-де жұмыс істесе де, MySQL MINUS қолдамайды. Derived table c ешқандай мәні бағаны жоқ; t1.value дегенді білдірдіңіз бе? Сондай-ақ, t1 және t2-ге қарсы тик және refid сілтемесін ауыстырғаныңыз жөн.
қосылды автор outis, көзі

Егер сіз «кек» және «қолайлы» мәндеріңізді алдын-ала білсеңіз,

  1. Барлық ықтимал белгілер мен мәндерді қамтитын көмекші кестені жасаңыз.
  2. Содан кейін кестедегі көмекші кестеден қосылыңыз және деректер кестеңізге қосыңыз.

Егер сіз «кәдімгі» және «қолайлы» мәндеріңізді білмесеңіз, сіз бұл әдісті әлі пайдалана аласыз, бірақ статикалық көмекші кестенің орнына динамикалық түрде жасалуы керек.

0
қосылды
Қандай жолдардың болмайтындығы белгісіз. Сұрақты қосу үшін оны өңдеңіз.
қосылды автор Chadwick, көзі