sql >> Databasteknik >  >> RDS >> Mysql

MySQL-hjälp:Optimera uppdateringsfråga som anger rankning enligt ordning på en annan kolumn

Först skulle jag ändra budget , cost och rank_score till heltal eller annan numerisk datatyp och istället för

UPDATE table_name
SET rank_score = CONCAT(cost, budget) ;

Då skulle du använda:

UPDATE table_name
SET rank_score = cost * 1000 + budget * 1  ;

Det är lättare då eftersom du inte behöver hantera strängfunktioner och att ha något som:

SELECT * 
FROM table_name
WHERE (conditions...)
ORDER BY rank_score DESC

(Parentes:har en parameter (1000 ) inställd så högre än den andra (1 ) motsvarar att ha en beställning på cost, budget . Prova detta för att kontrollera:

SELECT * 
FROM table_name
ORDER BY cost DESC
       , budget DESC

Så du kan väl släppa rank_score sammantaget, såvida du naturligtvis inte planerar att göra experiment med olika parametervärden.

Som andra har påpekat är det inte bästa praxis att ha ett fält som inte lagrar data utan en beräkning. Det är avnormalisering. I stället håller du tabellen normaliserad och låter databasen göra beräkningarna varje gång du behöver den:

SELECT id, budget, cost, 
       cost*1000 + budget*1 AS rank_score_calculated
FROM table_name
ORDER BY rank_score_calculated DESC

rank_score_calculated lagras inte i exemplet ovan. På så sätt behöver du inte uppdatera det beräknade fältet varje gång en budget eller en kostnad ändras eller en ny rad läggs till i tabellen.

Det finns bara en nackdel. Om tabellen är riktigt stor och du behöver den frågan (och beräkningen) göras av många användare och väldigt ofta, och tabellen uppdateras ganska ofta, kan det göra din databas långsammare. I så fall bör man börja fundera på att lägga till ett sådant fält.

Det andra fallet är när man behöver en absolut rank över alla tabellrader, som ditt behov. Eftersom MySQL inte har några "fönster"-funktioner är det väldigt svårt att skriva en sådan fråga i ren SQL.)

Rangen kan beräknas med hjälp av MySQL-variabler

SELECT *
     , @rownum:[email protected]+1 AS rank_calculated
FROM table_name
   , (SELECT @rownum:=0) AS st
ORDER BY rank_score DESC

Och om du vill placera dessa värden i rank , använd:

UPDATE table_name
         JOIN
         ( SELECT id
                , @rownum:[email protected]+1 AS rank_calculated
           FROM table_name
              , (SELECT @rownum:=0) AS st
           ORDER BY rank_score DESC
         ) AS r
         ON r.id = table_name.id
SET table_name.rank = r.rank_calculated ;

Ovanstående två frågor är inte ren SQL. Du kan undersöka alternativet att flytta till ett annat daabase-system som stöder fönsterfunktioner, som Postgres, SQL-Server eller Oracle.



  1. Varför är min sökfråga med flera kolumner dramatiskt långsammare än motsvarande frågor med en kolumn, även med ett index med flera kolumner?

  2. Sortera efter kolumn ASC, men NULL-värden först?

  3. Oracle - Kan inte använda *-tecken med annan kolumn i select-satsen

  4. MySQL CASE-sats och REGEXP