Sybase only Last Value - sql

I'm looking for a solution for this case:
select pimpfung.idpatientklinik, pimpfung.idpatient_vaccination, pimpfung.datum
From ictq.pimpfung
order by pimpfung.idpatientklinik
Output is:
idpatientklinik;idpatient_vaccination;datum
1;5500;01.02.2001
1;5567;05.09.2003
3;7766;22.08.2005
3;8899;25.09.2006
3;8900;29.09.2006
But I want the output like this:
1;5567;05.09.2003
3;8900;29.09.2006
(only the last values sort by "pimpfung.datum" desc)
How to do that ?
Thank you and sorry for my bad english ;-)

You can use a correlated subquery:
select p.*
from pimpfung p
where p.datum = (select max(p2.datum)
from pimpfung p2
where p2.idpatientklinik = p.idpatientklinik
);
With an index on (idpatientklinik, datum) this is often the fastest approach.
Here is a db<>fiddle (which uses SQL Server but this is all standard SQL).

Related

Fetch latest date records with group by

I am trying to fetch the records with latest records with unique report_ids (col_1_0_ ).
Possible group by col_1_0_ and fetch the latest of that group record using this column col_10_0_ timestamp.
I tried to search this forum to find the way but it did not worked for me . It will be helpful if anyone help me to find the similar thread or help to make to get the results.
col_1_0_|ppi_event_id|col_2_0_ |col_10_0_ |
--------|------------|--------------------------|-----------------------|
149056| 3249|Draft |2020-08-25 13:01:49.016|
149056| 3249|Submitted | 2020-08-25 13:10:22.01|
149056| 3249|Submitted to administrator|2020-08-25 13:12:39.367|
149056| 3249|Validated |2020-08-25 13:13:28.879|
149060| 3249|Submitted to administrator|2020-08-25 13:32:41.924|
The expected result is
col_1_0_|ppi_event_id|col_2_0_ |col_10_0_ |
--------|------------|--------------------------|-----------------------|
149056| 3249|Validated |2020-08-25 13:13:28.879|
149060| 3249|Submitted to administrator|2020-08-25 13:32:41.924|
Anyone help in this regard.
Update : I have tried the solution mentioned below but sometimes it shows the first record "Draft" rather than "Validated"
Any other option to try ?
In Postgres, I would recommend using distinct on: that's a nice extension to the SQL standard, that was built exactly for the purpose you describe.
select distinct on (col_1_0) t.*
from mytable t
order by col_1_0, col_10_0_ desc
Traditional SQL format is to use row_number()
Demo
SELECT * FROM (
SELECT A.*,
ROW_NUMBER() OVER( PARTITION BY col_1_0_ ORDER BY col_10_0_) AS RN
FROM TABLE1 A ) X WHERE RN = 1;

Getting error "SQL compilation error: Unsupported subquery type cannot be evaluated"

Am new to Snowflake programming though I had much experience in Oracle DB.
When am running the below query in Snowflake am getting the error as
SQL compilation error: Unsupported subquery type cannot be evaluated
SELECT organization_id,
inventory_item_id,
revision,
effectivity_date,
revision_label,
revision_id
FROM cg1_mtl_item_revisions_b mir
WHERE effectivity_date IN
(SELECT FIRST_VALUE (ir2.effectivity_date)
OVER (ORDER BY ir2.effectivity_date DESC)
effectivity_date
FROM cg1_mtl_item_revisions_b ir2
WHERE ir2.inventory_item_id = mir.inventory_item_id
AND ir2.organization_id = mir.organization_id
AND ir2.effectivity_date <= CURRENT_DATE
AND ir2.implementation_date IS NOT NULL)
AND mir.revision IN
(SELECT FIRST_VALUE (ir3.revision)
OVER (ORDER BY ir3.revision DESC)
revision
FROM cg1_mtl_item_revisions_b ir3
WHERE ir3.inventory_item_id = mir.inventory_item_id
AND ir3.organization_id = mir.organization_id
AND ir3.implementation_date IS NOT NULL
AND ir3.effectivity_date = mir.effectivity_date);
Am I missing something here??
Can someone plz help me here.
Thanks in Advance,
Sudarshan
The Snowflake database doesn't support correlated subqueries as extensively as Oracle does.
You have to find a way to rewrite, eg. using
WITH <common table expressions ...>
SELECT ...
JOIN ...
You seem to want the latest revision from the latest effective date. Window functions are probably a better approach in any database:
SELECT mir.* -- whatever columns you want
FROM (SELECT mir.*,
ROW_NUMBER() OVER (PARTITION BY mir.inventory_item_id, mir.organization_id
ORDER BY mir.effectivity_date DESC, mir.revision DESC) as seqnum
FROM cg1_mtl_item_revisions_b mir
) mir
WHERE seqnum = 1;
I have figured out that the third condition of the join in the last sub-query is throwing this error. If we comment out the following line then the code returns data:
{ AND ir3.effectivity_date = mir.effectivity_date }
So it seems three join conditions in a sub-query are not getting supported.
We need to work out on finding an alternate piece of code to satisfy the above condition so that we get the correct result set.
Another approach may be to use lateral joins - https://docs.snowflake.com/en/sql-reference/constructs/join-lateral.html
One important thing about lateral joins is it will only return matched records.

Negative comparison with ActiveRecord

I have two tables:
sales
period_id
customer_id
product_id
value
total_sales
period_id
customer_id
product_id
value
I want to select every combination of period_id and customer_id that exists on sales but don't exists on total_sales. I believe there's a short way to do this. But every approach I thought involves N+1 queries.
How can I do this?
In my opinion this is precisely the case where it's reasonable to diverge from the purist ActiveRecord approach and bring some SQL to the table. This should do the trick perfectly well:
Sale.find_by_sql("
SELECT * FROM sales WHERE NOT EXISTS (
SELECT 1 FROM total_sales
WHERE total_sales.period_id = sales.period_id AND
total_sales.customer_id = sales.customer_id)
")
I suppose it also can be done in a more ActiveRecordish style, but it will most certainly lose clarity of the code.
Of course if you ever drop this to you codebase, you really should wrap it in a method and leave in the model, so that SQL code at least doesn't bleed into the controller.
Hope this helps!
P.S. Oh, here's the SQL fiddle I used to test this out: http://sqlfiddle.com/#!15/eaf1d/1
How about you first get the list that matches, then use that to get the rows that you actually want:
unwanted_ids = Sale.joins('inner join total_sales on sales.period_id = total_sales.period_id and sales.customer_id = total_sales.customer_id').pluck('distinct sales.id')
wanted_rows = unwanted_ids.any? Sale.where('id not in (?)', unwanted_ids) : Sale.all
wanted_rows.select(:period_id, :customer_id) #if you only want these two
This way you only need two queries.
EDIT:
You can also do this:
Sale.joins('left outer join total_sales on sales.period_id = total_sales.period_id and sales.customer_id = total_sales.customer_id').where('total_sales.period_id is null')
Does it in one query

Oracle: An elegant way to take the first n record (top-k query)

Let's assume we want to take the first 1 record of a resultset. Is there a more elegant way to do it?
WITH temp
AS ( SELECT WKFC_CRONOLOGIA_ID
FROM SIUWKF.WKF_CRONOLOGIA c
WHERE Ogg_oggetto_id = vOGG_ID
AND TOG_TIPO_OGGETTO_ID = vTOG
AND C.WKFC_DATA_FIN = TO_DATE ('31/12/9999', 'DD/MM/YYYY')
AND Wkfc_Tipo = 'STATO'
ORDER BY WKFC_DATA_INI DESC)
SELECT WKFC_CRONOLOGIA_ID
INTO vCRONOLOGIA_ID
FROM temp
WHERE ROWNUM = 1;
I think your solution is alright. The only other solution with Oracle is to use the row_number() analytical function but this makes it less elegant. Other databases have the TOP 1 statement but there is no other Oracle equivalent to it than ROWNUM outside a subquery when you have an ORDER BY in use. I agree to use WITH which makes it more readable. The following might be written faster but I am not sure if it is more elegant. Maybe a matter of taste:
SELECT * FROM
( SELECT WKFC_CRONOLOGIA_ID
FROM SIUWKF.WKF_CRONOLOGIA c
WHERE Ogg_oggetto_id = vOGG_ID
AND TOG_TIPO_OGGETTO_ID = vTOG
AND C.WKFC_DATA_FIN = TO_DATE ('31/12/9999', 'DD/MM/YYYY')
AND Wkfc_Tipo = 'STATO'
ORDER BY WKFC_DATA_INI DESC)
WHERE ROWNUM = 1
This is what Oracle SQL manual says about ROWNUM and top-N reporting and confirms your way in doing it.
Source Oracle® Database
SQL Language Reference
11g Release 2 (11.2)
E26088-01

How can I eliminate the subquery from this sql query?

I have a query which should work, but it seems I am a victim of a poor database technology. I need to run the query below on a Pervasive SQL database. The manufacturer of the product using Pervasive tells me the version they are using is 10 which should support subqueries, but I have yet to be able to run even a simple subquery. So, I am wondering if the following query can be rewritten to eliminate the subquery:
SELECT
OuterTime.Employee,
OuterTime.Date,
OuterTime.Pay_ID,
OuterTime.Description,
OuterTime.Equipment,
OuterTime.JC_Cost_Code,
OuterTime.JC_Category,
OuterTime.Units,
(
SELECT
SUM(SubQueryTime.Units)
FROM
PRT_NEW__TIME AS SubQueryTime
WHERE
SubQueryTime.Employee = OuterTime.Employee
GROUP BY
SubQueryTime.Employee
) AS TotalHoursForEmp
FROM
PRT_NEW__TIME AS OuterTime
In standard SQL you can do this, though I have no idea about PervasiveSQL specifically...
SELECT
OuterTime.Employee,
OuterTime.Date,
OuterTime.Pay_ID,
OuterTime.Description,
OuterTime.Equipment,
OuterTime.JC_Cost_Code,
OuterTime.JC_Category,
OuterTime.Units,
COALESCE(TotalHoursForEmp.TotalUnits, 0) AS TotalUnits
FROM
PRT_NEW__TIME AS OuterTime
LEFT JOIN
(
SELECT
Employee,
SUM(Units) AS TotalUnits
FROM
PRT_NEW__TIME
GROUP BY
Employee
)
AS TotalHoursForEmp
ON TotalHoursForEmp.Employee = OuterTime.Employee
Not a Pervasive SQL guy, but would this work? Not sure it accomplishes your query goals:
SELECT
OuterTime.Employee,
OuterTime.Date,
OuterTime.Pay_ID,
OuterTime.Description,
OuterTime.Equipment,
OuterTime.JC_Cost_Code,
OuterTime.JC_Category,
SUM(OuterTime.Units) AS TotalHoursForEmp
GROUP BY OuterTime.Employee, OuterTime.Date, OuterTime.Pay_ID,
OuterTime.Description, OuterTime.Equipment, OuterTime.JC_Cost_Code,
OuterTime.JC_Category
FROM
PRT_NEW__TIME AS OuterTime