Pobranie klientów rozpoczynających współpracę miesiąc wcześniej niż wystawienie faktury

0

Musze napisać zapytanie gdzie jedym z warunków jest aby wyciągnąć TYLKO tcyh klientów ktorzy rozpoczeli współpracę miesiąc wcześniej na podstawie datytay wystawienia faktury. Udało mi się wyciągnać rekordy które miały wystawioną fakturę miesiąc temu ale nie wiem jak sprawdzić warunek który nie bedzie wyciagał mi rekordów w przypadku jak była wystawiona faktura w zeszłym miesiacu i wcześniej.

np. Klient a faktura 12.02.2020, 05.01.2023 to jest ok
Klient b faktura 05.012023, 20.12.2022 - a tego kleinta juz nie chce na liscie

0

nie wiem jaka baza ale np jak bys uzyl DATEDIFF i porwonal miesiace? ze np pokaz tylko te co sa miesiac temu ale wczesniejszych juz nie

AND DATEDIFF(MONTH, invoices.created_at, GETDATE()) = 1

ewentualnie EXISTS

WHERE EXISTS (
    SELECT *
    FROM invoices
    WHERE DATEDIFF(MONTH, invoices.created_at, GETDATE()) = 1
)
0

jak oracle to moze cos w stylu

  SELECT *
  FROM invoices
  WHERE created_at >= ADD_MONTHS(TRUNC(SYSDATE, 'MONTH'), -2)
0

Wyżej chyba nie zrozumieli pytania.
Poniżej masz zapytanie na klientów którzy nie mieli żadnej faktury starszej niż -1 miesiąc.
Kod PostgreSQL ale dostosujesz do swojej bazy.

SELECT *
FROM clients
WHERE id NOT IN (
  SELECT DISTINCT client_id
  FROM invoices
  WHERE created_at < now() - '1 month'::interval
)
0

Sposobów jest wiele, ty musisz wybrać ten najefektywniejszy dla siebie.

SELECT distinct i_1.client_id
FROM invoices i_1
WHERE i_1.client_id NOT IN (
  SELECT i_2.client_id
  FROM invoices i2
  WHERE i_2.issue_date < add_months(trunc(sysdate), -1)
  AND i_2.client_id is not null -- jeśli klient jest obowiązkowy w fakturze, to można to pominąć
);

-- wszystkie faktury minus faktury starsze niż miesiąc
SELECT i_1.client_id
FROM invoices i_1
MINUS
SELECT i_2.client_id
FROM invoices i_2
WHERE i_2.issue_date < add_months(trunc(sysdate), -1)
;

SELECT distinct i_1.client_id
-- tu ewentualnie join z klientami, jeśli potrzebujesz nazwę klienta itd.
FROM invoices i_1
WHERE not exists
 (
  SELECT 1
  FROM invoices i2
  WHERE i_2.issue_date < add_months(trunc(sysdate), -1)
  AND i_2.client_id = i_1.client_id
);

0

Napisałem coś takiego i chce użyć NOT EXIST ale jak dokładam go do zapytania dostaje błąd An internal error has occurred.
Cannot read field "query" because "this.this$0.curResultsContainer" is null

SELECT gc.cust_name, sc.cust_id, substr(i.invoice_date, 0, 6) AS inv_date, sum(i.amount) AS turnover
FROM sal_contract sc
JOIN inv_invoice i ON
i.payer_cust_id = sc.cust_id
AND sc.contract_id = i.contract_id
AND i.invoice_date < to_char(sysdate, 'YYYYMM')|| '01'
AND i.test_flag = '0'
JOIN gen_customer gc ON
gc.cust_id = sc.cust_id
LEFT JOIN sal_contract OLD ON
old.cust_id = sc.cust_id
AND old.contract_end_date < to_char(sysdate, 'YYYYMMDD')
WHERE sc.first_contract_date >= to_char(add_months(sysdate,- 6), 'YYYYMM')|| '01'
AND sc.first_contract_date < to_char(sysdate, 'YYYYMM')|| '01'
AND sc.contract_status = '2'
AND sc.contract_end_date >= to_char(sysdate, 'YYYYMMDD')
AND sc.CUST_ID IN ('2139906', '2140120', '2140174', '2139800')
AND old.contract_id IS NULL
AND NOT EXISTS ( SELECT inv.invoice_date FROM inv_invoice inv WHERE inv.invoice_date > TO_CHAR((ADD_MONTHS(SYSDATE, - 2))
GROUP BY gc.cust_name, sc.cust_id, substr(i.invoice_date, 0, 6);
0

No bo zoba, masz otwarte 4 nawiasy a zamykasz tylko 2

AND NOT EXISTS ( SELECT inv.invoice_date FROM inv_invoice inv WHERE inv.invoice_date > TO_CHAR((ADD_MONTHS(SYSDATE, - 2))

powinno byc

AND NOT EXISTS ( SELECT inv.invoice_date FROM inv_invoice inv WHERE inv.invoice_date > TO_CHAR((ADD_MONTHS(SYSDATE, - 2)))
)
0

A po co robisz TO_CHAR na dacie? INVOICE_DATE jest typu VARCHAR2? Tak samo inne daty, jeśli mają format DATE czy TIMESTAMP, to porównujesz je bezpośrednio z datą a nie znakami. Bo wtedy robi się niejawna konwersja.

contract_end_date < sysdate

a lepiej zapewne (bo raczej contract_end_date ma godzinę = 0000):

contract_end_date < trunc(sysdate)

Zamiast:

to_char(sysdate, 'YYYYMM')|| '01'

robisz obcięcie daty do pierwszego dnia miesiąca:

trunc(sysdate, 'MM')

Potem

to_char(add_months(sysdate,- 6), 'YYYYMM')|| '01'

zmień na

trunc(add_months(trunc(sysdate),- 6), 'MM')

Generalna zasada, jeśli masz dane bez godzin (tj. równe 0000), to porównuj też z parametrami bez godzin. Jeśli zawierają godziny, porównuj z jakąś stałą godziną np. 2359, albo 0000 dnia następnego, aby uniknąć "pływających danych" tj. różnych wyników zależnie od godziny wykonania zapytania (no chyba, że działasz na danych typowo związanych z czasem i chcesz widzieć dokładnie te utworzone przed bieżącą godziną).

Kolejna rzecz, CUST_ID wygląda na liczbę, po co konwersja na znaki?

CUST_ID IN (2139906, 2140120, 2140174, 2139800)

Zawsze sprawdzaj typ danych w definicji tabeli i używaj funkcji dostosowanych do tego typu. Jeśli robisz niejawne konwersje jak powyżej, to nie są one odporne na zmianę ustawień regionalnych, dotyczy to dat oraz liczb.
Ty sobie zrobisz konwersję daty do YYYYMMDD, a sesja będzie miała ustawione DDMMYYYY, więc baza porówna np. '31122023' z '20231231'
w warunku:

old.contract_end_date < to_char(sysdate, 'YYYYMMDD')

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