Welcome to Sign in | Help
in Search

Ajutor optimizare interogare

Last post 02-02-2008, 2:23 PM by ThePuiu. 8 replies.
Sort Posts: Previous Next
  •  02-01-2008, 1:24 AM 3901

    Ajutor optimizare interogare

    Se dau 3 tabele:

    [FACTURI](
    [ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
    [NUMAR] [numeric](18, 0) NULL,
    [DATA] [datetime] NULL)

    [DETAIL](
    [ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
    [ID_FACTURA] [numeric](18, 0) NULL,
    [ID_PRODUS] [numeric](18, 0) NULL)

    [PRODUSE](
    [ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
    [PRODUS] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL)

    DETAIL.ID_FACTURA = FACTURI.ID
    DETAIL.ID_PRODUS = PRODUSE.ID

    In tabela FACTURI se gasesc antetele facturii (numar factura si data emitere), in DETAIL sint produsele vindute sub forma de coduri care se regasesc in tabela PRODUSE. In tabela produse se gasesc un numar mare (mii de produse). Ce as vrea sa fac intr-un mod cit mai elegant: un tabel care sa aiba ca si capete de coloana:
    1. Cod produs
    2. Ziua 1 a lunii
    3. Ziua 2 a lunii
    -------------------
    32. Ziua 31 a lunii
    33. Total per produs

    Ca si linii in tabel vor fi:
    Coloana 1:
    produsele in ordine alfabetica
    Coloana 2: numarul de aparitii [count(PRODUS1)] din ziua 1 a lunii
    Coloana 3: numarul de aparitii [count(PRODUS1)] din ziua 2 a lunii
    etc
    Coloana 33: suma aparitiilor pt cele 31 zile pt produsul PRODUS1

    Numarul de coloane trebuie determinat automat (nu toate lunile au 31 de zile!), chiar daca tabela care va contine rezultatul va avea un nr fix de coloane, zilele lipsa din luna vor contine 0 sau null.
    Se poate face chestia asta fara a face select count(P1), count(P2), etc de 31 de ori? As dori ceva cit de cit rapid, iar pe mine ma cam depaseste!

    Multumesc anticipat!

  •  02-01-2008, 8:52 AM 3903 in reply to 3901

    Re: Ajutor optimizare interogare

    Dacă te interesează o soluţie pentru SQL 2000, atunci poţi să faci ceva de genul:
    SELECT Produs,
      SUM(CASE WHEN DAY(Data)=1 THEN 1 ELSE 0 END) AS [1],
      SUM(CASE WHEN DAY(Data)=2 THEN 1 ELSE 0 END) AS [2],
      SUM(CASE WHEN DAY(Data)=3 THEN 1 ELSE 0 END) AS [3],
      SUM(CASE WHEN DAY(Data)=4 THEN 1 ELSE 0 END) AS [4],
      SUM(CASE WHEN DAY(Data)=5 THEN 1 ELSE 0 END) AS [5],
      SUM(CASE WHEN DAY(Data)=6 THEN 1 ELSE 0 END) AS Devil,
      SUM(CASE WHEN DAY(Data)=7 THEN 1 ELSE 0 END) AS [7],
      SUM(CASE WHEN DAY(Data)=8 THEN 1 ELSE 0 END) AS Music,
      SUM(CASE WHEN DAY(Data)=9 THEN 1 ELSE 0 END) AS [9],
      SUM(CASE WHEN DAY(Data)=10 THEN 1 ELSE 0 END) AS [10],
      SUM(CASE WHEN DAY(Data)=11 THEN 1 ELSE 0 END) AS [11],
      SUM(CASE WHEN DAY(Data)=12 THEN 1 ELSE 0 END) AS [12],
      SUM(CASE WHEN DAY(Data)=13 THEN 1 ELSE 0 END) AS [13],
      SUM(CASE WHEN DAY(Data)=14 THEN 1 ELSE 0 END) AS [14],
      SUM(CASE WHEN DAY(Data)=15 THEN 1 ELSE 0 END) AS [15],
      SUM(CASE WHEN DAY(Data)=16 THEN 1 ELSE 0 END) AS [16],
      SUM(CASE WHEN DAY(Data)=17 THEN 1 ELSE 0 END) AS [17],
      SUM(CASE WHEN DAY(Data)=18 THEN 1 ELSE 0 END) AS [18],
      SUM(CASE WHEN DAY(Data)=19 THEN 1 ELSE 0 END) AS [19],
      SUM(CASE WHEN DAY(Data)=20 THEN 1 ELSE 0 END) AS [20],
      SUM(CASE WHEN DAY(Data)=21 THEN 1 ELSE 0 END) AS [21],
      SUM(CASE WHEN DAY(Data)=22 THEN 1 ELSE 0 END) AS [22],
      SUM(CASE WHEN DAY(Data)=23 THEN 1 ELSE 0 END) AS [23],
      SUM(CASE WHEN DAY(Data)=24 THEN 1 ELSE 0 END) AS [24],
      SUM(CASE WHEN DAY(Data)=25 THEN 1 ELSE 0 END) AS [25],
      SUM(CASE WHEN DAY(Data)=26 THEN 1 ELSE 0 END) AS [26],
      SUM(CASE WHEN DAY(Data)=27 THEN 1 ELSE 0 END) AS [27],
      SUM(CASE WHEN DAY(Data)=28 THEN 1 ELSE 0 END) AS [28],
      SUM(CASE WHEN DAY(Data)=29 THEN 1 ELSE 0 END) AS [29],
      SUM(CASE WHEN DAY(Data)=30 THEN 1 ELSE 0 END) AS [30],
      SUM(CASE WHEN DAY(Data)=31 THEN 1 ELSE 0 END) AS [31],
      COUNT(*) AS Total
    FROM Facturi f
    INNER JOIN Detail m ON f.ID=m.ID_Factura
    INNER JOIN Produse p ON p.ID=m.ID_Produs
    WHERE Data BETWEEN '20060801' AND '20060831'
    GROUP BY Produs
    ORDER BY Produs


    Dacă ai SQL Server 2005, atunci poţi să foloseşti PIVOT:

    SELECT Produs,
      [1],[2],[3],[4],[5],Devil,[7],Music,[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31],
      [1]+[2]+[3]+[4]+[5]+Devil+[7]+Music+[9]+[10]+[11]+[12]+[13]+[14]+[15]+[16]+[17]+[18]+[19]+[20]+[21]+[22]+[23]+[24]+[25]+[26]+[27]+[28]+[29]+[30]+[31] as Total
    FROM (
      SELECT Produs, DAY(Data) AS Ziua
      FROM Facturi f
      INNER JOIN Detail m ON f.ID=m.ID_Factura
      INNER JOIN Produse p ON p.ID=m.ID_Produs
      WHERE Data BETWEEN '20060801' AND '20060831'
    ) AS X PIVOT (COUNT(Ziua) FOR Ziua IN (
      [1],[2],[3],[4],[5],Devil,[7],Music,[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31]
    )) AS P
    ORDER BY Produs


    Răzvan

    PS. Evident, semnele alea stupide reprezintă numerele care ar trebui să fie acolo. Nu ştiu cum fac ca să scriu un 6 între paranteze pătrate fără să apară drăcuşorul respectiv...
  •  02-01-2008, 10:04 AM 3904 in reply to 3903

    Re: Ajutor optimizare interogare - off topic

    rsocol:

    PS. Evident, semnele alea stupide reprezintă numerele care ar trebui să fie acolo. Nu ştiu cum fac ca să scriu un 6 între paranteze pătrate fără să apară drăcuşorul respectiv...

    [<spatiu>6<spatiu>]
    [ 6 ]

    Ignat Andrei
    http://serviciipeweb.ro/iafblog
  •  02-01-2008, 12:58 PM 3915 in reply to 3904

    Re: Ajutor optimizare interogare - off topic

    am uitat sa precizez...imi trebuie in Access....din pacate si codul de mai sus nu merge....Crying
    Daca nu stii access sa ma luminezi si pe mine (nici eu nu am mai lucrat cu el) o sa incerc sa vad cum pot sa-l retranscriu.....

    Multumesc pt raspuns!

  •  02-01-2008, 4:35 PM 3919 in reply to 3915

    Re: Ajutor optimizare interogare - off topic

    În Access există un Crosstab Query Wizard care te poate ajuta, însă ar trebui să faci un alt query înainte ca să poţi să-l foloseşti.

    Iar rezultatul ar trebui să fie ceva de genul:

    TRANSFORM COUNT(Produse.ID)
    SELECT Produse.Produs, COUNT(Produse.ID) AS Total
    FROM (Detail INNER JOIN Facturi ON Detail.ID=Facturi.ID) INNER JOIN Produse ON Detail.ID=Produse.ID
    GROUP BY Produse.Produs
    PIVOT DAY(Facturi.Data);

    Răzvan
  •  02-01-2008, 5:43 PM 3921 in reply to 3919

    Re: Ajutor optimizare interogare - off topic

    rsocol:
    În Access există un Crosstab Query Wizard care te poate ajuta, însă ar trebui să faci un alt query înainte ca să poţi să-l foloseşti.

    Iar rezultatul ar trebui să fie ceva de genul:

    TRANSFORM COUNT(Produse.ID)
    SELECT Produse.Produs, COUNT(Produse.ID) AS Total
    FROM (Detail INNER JOIN Facturi ON Detail.ID=Facturi.ID) INNER JOIN Produse ON Detail.ID=Produse.ID
    GROUP BY Produse.Produs
    PIVOT DAY(Facturi.Data);

    Răzvan

    COUNT din clauza SELECT poate fi eliminat
  •  02-01-2008, 9:40 PM 3923 in reply to 3921

    Re: Ajutor optimizare interogare - off topic

    huh! da, face exact ce vreau eu! stii doar ce problema mai este? trebuie sa generez un raport in crystal cu datele obtinute din query. Ma gindeam sa creez un table cu 31 coloane pt zile in care sa copiez rezultatul si din acesta sa afisez raportul. Cum se poate face un insert into cu rezultatele din acest query in tabela de care ziceam mai sus?

    Multumesc!

  •  02-02-2008, 8:42 AM 3924 in reply to 3923

    Re: Ajutor optimizare interogare - off topic

    Dar nu poţi să bazezi raportul direct pe query-ul de mai sus ? Dacă nu se poate, atunci mai faci un alt query care să adauge datele în tabel:
    INSERT INTO rezultat SELECT TheQuery.* FROM TheQuery;

    (vezi că în query designer-ul din Acces ai nişte tipuri de query-uri care de ajută la treburile astea: Make-Table Query şi Append Query)

    Răzvan
  •  02-02-2008, 2:23 PM 3925 in reply to 3924

    Re: Ajutor optimizare interogare - off topic

    da, merge, dar as vrea sa stiu daca nu se pot comasa cumva cele 2 query-uri in unul singur si sintaxa sa o pot folosi intr-o interogare direct in program. As vrea asta pt ca eu vreau sa schimb programatic un interval de timp care l-am adaugat primului query si nu stiu cum sa fac asta fara sa folosesc DAO. (lucrez in C# cu OLE DB).
View as RSS news feed in XML
Powered by Community Server (Commercial Edition), by Telligent Systems