SQL Query - Kilka praktycznych zapytań

0

Witam, teraz ja założyłem wątek i liczę na odrobinę dobrej woli i współpracy. Użytkuję "darmową" wersję Embarcadero® Delphi Community Edition 10.3.3, i mam parę pytań odnośnie zapytań SQL, a w szczególności ADOQuery.

  1. Czy mogę przechowywać w ADOQuery.SQL listę wszystkich zapytań i odwoływać się do nich po indeksie? W znalezionych przeze mnie prostych przykładach wszędzie mają po jednym wpisie.
  2. Chciałbym wykorzystać komponent ValueListEditor (Opis dla użytkownika | Polecenie SQL) - to oczywiście w opcjach programu, a użytkownik w programie będzie miał pole ComboBoxList w którym wybierze za pomocą przyjaznego opisu odpowiednie polecenie. I pytanie czy do ADOQuery muszę za każdym tylko jedno polecenie, czy mogę załadować wszystkie i odwoływać się po indeksie?

Oczywiście mam do wszystkich prośbę aby podzielili się informacjami o praktycznym wykorzystaniu QUERY nie koniecznie dla ADO - z góry dziękuję.

3

Zasadniczo ADOQuery.SQL to nic innego jak TStrings możesz zatem dodawać wiele stringów ale dalej będzie to jedno zapytanie. Jak zrobisz takie coś:

    ADOQuery1.SQL.Add('select * from dual');
    ADOQuery1.SQL.Add('union');
    ADOQuery1.SQL.Add('select * from dual');
    Caption := ADOQuery1.SQL[1];

to w caption pojawi ci się napis 'union' natomiast ADOQuery1.Open uruchomi całe zapytanie.

Jeśli chcesz w jednym komponencie uruchamiać różne query to zapronowałbym zwykły TList<string> ale skoro potrzebujesz to potem jeszcze jakoś captionować w combo to lepiej TDictionary<string,TStrings> :)

1

Według mnie, po pierwsze użyj FireDac-a a nie dbGo. Embarcadero rozwija tą technologię.
Po drugie, nie jestem zwolennikiem umieszczania kodu w komponentach (ogólnie w plikach dfm, czy też fmx w zależności od technologii) chociażby z tego powodu że trudniej się analizuje kod programu po jakimś czasie.
W tym momencie już sprawa wg. mnie jest rozwiązana. Możesz stworzyć sobie ile chcesz i jakich chcesz zapytań w czymkolwiek, TStringList, Memo, tablica, ComboBox, plik txt, cokolwiek przyjdzie ci do głowy i z tego źródła pobierać odpowiednie zapytania.

0

@robertz68: SQLNCLI11.1 (Provider) w komponencie ADOConnection aby połączyć się z MS SQL Server 2019 Express Edition. Zawsze wykluczam (wyłączam) i nie używam BCD i jakoś wszystko mi działa. Firedac obsługiwane jest bezproblemowo. Myślę szanowni Państwo, że co niektórych wiedza odnośnie platformy RAD Studio (w tym Delphi) to takie bardzo stare wiadomości i zaszufladkowanie, ale cóż każdy człowiek jedzie na stereotypach - lubimy pochopnie oceniać. :P

0
pstmax napisał(a):

@robertz68: SQLNCLI11.1 (Provider) w komponencie ADOConnection aby połączyć się z MS SQL Server 2019 Express Edition.

To nie jest zalecane połączenie dla MSSSQL 2019.
W ogóle NativeClient jest już passe wg Microsoft, ale działa bez problemu.
Teraz na topie jest nowy provider OLE DB lub ODBC.
FireDAC tego co prawda nie wspiera natywnie, ale... to w sumie nie jest problem.
Natomiast, żeby było jeszcze śmieszniej, wspiera to stare i nierozwijane dbGO, bo do ADO wystarczy doinstalować odpowiedni provider OLE DB (MSOLEDBSQL) i go użyć.

Zawsze wykluczam (wyłączam) i nie używam BCD i jakoś wszystko mi działa.

Tego się nie powinno wykluczać czy wyłączać, a mapować np. na Currency czy inny właściwy typ danych.
http://docwiki.embarcadero.com/RADStudio/Sydney/en/Data_Type_Mapping_(FireDAC)

Firedac obsługiwane jest bezproblemowo.

Eee... nie rozumiem.

Myślę szanowni Państwo, że co niektórych wiedza odnośnie platformy RAD Studio (w tym Delphi) to takie bardzo stare wiadomości i zaszufladkowanie, ale cóż każdy człowiek jedzie na stereotypach - lubimy pochopnie oceniać. :P

Oj tam, przecież to truizm i dotyczy w sumie wszystkiego.

0

Dodatkowe pytanie:
Mam tabelę DANEWE z polami LTT, DataLos, P1,P2,P3,P4,P5,P6,DzTyg i chciałbym za pomocą zapytania SQL (najlepiej jednego) wykonać:
Utworzyć nową tabelę DWSORT która będzie będzie miała pola DataLos, P1,P2,P3,P4,P5,P6 posortowane rosnąco według pola DataLos.
Czy jest to możliwe?

1

Jest to możliwe, tylko taka operacja nie ma sensu, ponieważ tabela tylko przechowuje dane, a o tym w jaki sposób zostaną przedstawione decyduje SELECT. W tym przypadku wystarczy posortować dane wg kolumny DataLos. Wcześniej tylko należy na bazie utworzyć indeks na tą kolumnę, żeby zapytanie nie obciążało serwera sql.

0

jeśli masz problemy z "ręcznym" tworzeniem tabel (czy tam całych baz) to użyj Microsoft SQL Management Studio, utwórz w nim konkretną, interesującą cię tabelę, następnie wg obrazka:
screenshot-20210427064331.png

taki gotowy skrypt możesz użyć w swojej aplikacji. Taki sposób zapewni ci że niczego nie pominiesz.

0

Rozumiem, wiem o tym. Po prostu irytuje mnie to, że muszę wywoływać przy każdym wyświetleniu, a użytkownik w zasadzie non-stop modeluje sobie zakresy wchodzące w skład podzbioru wycinanego za pomocą ustawiania wartości początkowej DataLos i wartości końcowej DataLos - to po pierwsze. Wrzucam zrzut ekranu z aplikacji dla lepszego zobrazowania.

Użytkownik ma mieć możliwość przeprowadzenia serii symulacji na ograniczonym roboczym wycinku danych, może sobie określić jego zawartość poprzez wskazanie daty początkowej i daty końcowej lub poprzez podanie ilości losowań jaka ma należeć do roboczego zbioru.

fo]

W drugim kroku ma ten roboczy zbiór - podzielić na serie (mniejsze zbiory (serie mogą mieć rozmiar od 3 losowań do 468 losowań + reszta, która pozostaje po operacji DIV - na zrzucie masz akurat ustawioną ilość w serii na 18). Następnie Ilość powtórzeń L1, L2, L3,L4,L5,L6 ma być w danej serii ma być zgrupowana, potem dalsze czynności o których nie ma co na razie pisać) Tak więc, doszedłem do wniosku, że mądrze będzie poszczególne operacje, a dokładnie ich wyniki zapisywać.

Tok mojego rozumowania:

  1. Wycinam z całego zbioru wycinek np 200 losowań po czym zapisuje go w osobnej tabeli poprzez parametry (DataLos_początek,DataLos_koniec,ilość_serii_tutaj-18)
  2. Następnie w pełnych podzbiorach składających się tutaj z 18 losowań, czyli 200 DIV 18 = 11 grupuję powtarzające się wystąpienia liczb w kolumnach L1...L6 + reszta)
  3. Potem następne operacje...

Oczywiście użytkownik będzie mógł w ten sposób stworzyć sobie różne warianty i chciałby móc je sobie wyświetlić w osobnych okienkach w jemu tylko znanym celu celu :P)
Dalej mają być, jeszcze operacje...

Dlatego zależy mi na tym aby, nie tyle zapisywać wyniki, co parametry tych wyników. Można to porównać - zapis bitmapy (bit po bicie) i zapis grafiki wektorowej (zapisuję współrzędne i parametry oraz info o bryły geometrycznej) Nie wiem czy opisałem to w zrozumiały sposób - mam nadzieję, że tak.

Wracając do głównego wątku, wiem, że wszystko będzie wykonywane po stronie klienta i dlatego zależy mi aby nie wykonywać ich za każdym razem, tylko pobierać.

0

ja w programach w których muszę filtrować dane po datach (dokumenty sprzedaży itp.) nad gridem umieszczam pasek filtrów:
screenshot-20210427120603.png
To co tam ustawię jest aktualne do czasu aż ręcznie zmienię zakres. Można by nawet umieścić checkbox-a i zapamiętać filtr na stałe dla danego użytkownika.

0

ale wiesz o tym, że aby pobrać te dane po odfiltrowaniu musisz wykonać SELECT?
każda zmiana filtru spowoduje, że będziesz musiał tworzyć nową tabelę z danymi lub czyścić istniejącą i wrzucać do niej nowe rekordy, do czego będzie potrzebny dodatkowy czas.
W skrócie to będzie wyglądało tak:

  1. operator wybiera zakres
  2. tworzysz tabelę wraz z indeksami na dane (lub czyścisz tabelę istniejącą)
  3. pobierasz dane:
insert into nowa_tabla
select * from tabela where datalos between '2020-01-01' and '2020-12-31'
  1. pobierasz dane z tabeli:
select * from nowa_tabela

A jeżeli pominiesz przenoszenie danych do nowej tabeli to 2 kroki (drugi i czwarty, a z 3 wykreślasz linię insert into nowa_tabela) z tego odpadają, czyli masz mniej operacji, które zajmują mniej czasu oraz zużywają mniej zasobów.

Chyba, że faktycznie na tej ograniczonej ilości danych będziesz wykonywał później miliony operacji to może ich wydzielenie ma sens, ale to musiałbyś sam sprawdzić

0

@Paweł Dmitruk: Wkradło się małe nieporozumienie do naszej wymiany zdań - tabela ma być utworzona jedna, a kombinacje filtrów i zakresów mają tworzyć rekordy w tej tabeli. W ten sposób, użytkownik będzie mógł wykonać sobie różne scenariusze i potem tylko je podmieniać lub porównywać.Zrzut ekranu 2021-04-27 Krok 2.png
Dołączam pozostałe zrzuty ekranu abyście mieli pełen obraz. Zrzut ekranu 2021-04-27 Opcje.png
Na ostatnim zrzucie powtórzyłem pierwszy ekran - ten ma włączony ekran i ustawiony zakres roboczy na 360 losowań od 03-12-2013 do 09-06-2016 co daje zbiór 360 losowań. Teraz mam te losowania podzielić na podzbiory 360 DIV 18 = 20 i wykonać na nich grupowanie:

SELECT P1, COUNT(P1) AS Licz_Jeżeli FROM [dbo].[DANEWE] WHERE Data Between '2013-12-01' AND '2013-12-31' GROUP BY P1

I wynik tego zapytania chciałbym zapisać w nowej tabeli powiedzmy o nazwie DWSORT - z tym mam problem. Czy ktoś mógłby mi pomóc?
Czy polecenie jest poprawne?
Jak dopełnić dane o liczny które nie występują (jest 1,2,3,4, 5 - 26 potem 31,32, 40) a chcę to zapisywać sobie w pliku lokalnym (Krok 2)

Zrzut ekranu 2021-04-27 150449.pngZrzut ekranu 2021-04-27 150449.png

Mam też takie warianty zapytań:

SELECT P1, COUNT(P1) FROM DANEWE WHERE DataLos Between '2013-12-03' AND '2016-12-31' GROUP BY P1 ORDER BY P1;
Select * From DANEWE WHERE DataLos Between '2013-12-03' AND '2016-06-09' Order By DataLos;

Jak mam chwila (przy każdej zmianie AdoQuery.Clear, AdoQuery.SQL.Add('') czyścić i dodawać, to robota głupiego. Może ktoś mi podpowie jak wykorzystać coś na wzór ValueListEditor aby mieć takie różne kombinacje pozapisywane i to jeszcze w zewnętrznym pliku tekstowym - łatwo poprawić zapytanie nawet poza programem

Należy pamiętać, że wraz z dodawaniem następnych kroków w programie zapytania mogą stać się tak złożone, że aż bezsensowne albo nawet niewykonalne - stąd pomysł na tabele z pośrednimi nazwijmy to wyliczeniami.

Ostatnia sprawa to temat Kalendarza, który miałby po rozwinięciu Zrzut ekranu 2021-04-27 Czy jest taki kalendarz pod jednym TDataTimePicker lub TCalendar.png daty miałby od razu 3 miesiące - ma ktoś pomysł jak to ugryźć?

0

Jeśli dobrze zrozumiałem ten fragment:

Jak mam chwila (przy każdej zmianie AdoQuery.Clear, AdoQuery.SQL.Add('') czyścić i dodawać, to robota głupiego. Może ktoś mi podpowie jak wykorzystać coś na wzór ValueListEditor aby mieć takie różne kombinacje pozapisywane i to jeszcze w zewnętrznym pliku tekstowym - łatwo poprawić zapytanie nawet poza programem

to wywołanie zapytania z zewnętrznego źródła nie jest żadnym problemem.
Ja bym do tego użył np. listbox lub combobox i pobierał dane z pliku txt. W każdej linii jedna komenda.

1 użytkowników online, w tym zalogowanych: 0, gości: 1