How to get the last date of record from multiple table in Oracle SQL [duplicate] - sql

This question already has answers here:
Fetch the rows which have the Max value for a column for each distinct value of another column
(35 answers)
GROUP BY with MAX(DATE) [duplicate]
(6 answers)
Get value based on max of a different column grouped by another column [duplicate]
(1 answer)
Oracle SQL query: Retrieve latest values per group based on time [duplicate]
(2 answers)
How to get the last row of an Oracle table
(7 answers)
Closed 4 years ago.
Wrote this SQL and just need some help how to show the last WO created date on my sql. I tried the max(evt_created "WO Date Created" and group all my selected field and it's not working.
select
obj_udfchar09 "700 Whse - Slot #",
obj_person "Assign To",
obj_category "Category",
obj_class "Class",
obj_commiss "Commission Date",
OBJ_COSTCODE "Cost Code",
R5REP.REPGETDESC('EN','PERS',obj_user,NULL,NULL) "Created By",
OBJ_CREATED "Date Created",
obj_mrc "Department",
obj_desc "Description",
obj_variable1 "Equipment Book #",
obj_code "Equipment/Asset Tag",
obj_location "Location",
obj_udfchar03 "Maintenance Division",
obj_manufact "Manufacturer",
obj_manufactmodel "Model",
obj_notused "Out of Service",
obj_variable2 "Part",
obj_production "Production",
obj_variable5 "Refrigerant Amount",
obj_variable6 "Refrigerant Type",
obj_serialno "Serial Number",
STC_PARENT "System",
STC_PARENTTYPE "Type",
EVO_TOTAL AS "Cost Summary",
evt_code "WO",
evt_created "WO Date Created",
stc_parent "System Code",
nvl(
(select sum(nvl(a.evo_total, 0))
from r5eventcost a
where a.evo_event in (select evt_code
from r5events
where evt_object = obj_code
and evt_object_org = obj_org
and evt_rstatus in ('R', 'C')
and evt_rtype in ('JOB', 'PPM'))), 0)
+
nvl(
(select sum(nvl(b.avc_total, 0))
from r5eventcost_archive b
where b.avc_event in (select aev_code
from r5events_archive
where aev_object = obj_code
and aev_object_org = obj_org
and aev_rstatus in ('R', 'C')
and aev_rtype in ('JOB', 'PPM'))), 0) "Total Cost"
from
r5objects, r5structures, r5events, r5eventcost
where
obj_code = stc_child (+) and
obj_rstatus = 'I' and
obj_code like '1%' and
EVT_CODE = EVO_EVENT (+) AND
EVT_OBJECT = OBJ_CODE (+) and
obj_code in ('1064016','1004188','1108146') and
STC_PARENTTYPE = 'S'

You can order your query by WO Date Created desc and return the first row.
Maybe there are best ways to do what you need but it works.
An example,
SELECT *
FROM <your_table> pu
INNER JOIN (
SELECT *
FROM (SELECT ROWNUM, a.max_date
FROM (SELECT MAX(<your_date_column>) AS max_date
FROM <your_table>
GROUP BY <your_date_column>
ORDER BY <your_date_column> DESC) a)
WHERE ROWNUM = 1) b ON pu.<your_date_column> = b.max_date;

Related

Get a cumulative sum in SQL

I am struggling with a postgresql query where I am trying to get the cumulative sum instead of the sum, by date truncated.
Here is my original query
SELECT date_trunc('month', "public"."stock_transaction"."created_at") AS "created_at", "Category"."name" AS "Category - name", sum("public"."stock_transaction"."cost") AS "sum"
FROM "public"."stock_transaction"
LEFT JOIN "public"."product" "Product" ON "public"."stock_transaction"."product_id" = "Product"."id" LEFT JOIN "public"."category" "Category" ON "Product"."category_id" = "Category"."id"
WHERE ("public"."stock_transaction"."owner_id" = {{organization.id}}::uuid
AND {{createdAt}}
AND "Product"."recipe" = FALSE)
GROUP BY date_trunc('month', "public"."stock_transaction"."created_at"), "Category"."name"
ORDER BY date_trunc('month', "public"."stock_transaction"."created_at") ASC, "Category"."name" ASC
and it looks like this
It's generated by metabase. createdAt is a date field filter and organizationId an uuid.
The result should be an increasing bar chart with the value of each month added to the previous month.
I have tried with subqueries but I have a hard time solving every SQL error I jump into.
Is there a SQL boss around who can help? Thanks :D
you just need a window function to get a cumulative sum :
SELECT s."created_at"
, s."Category - name"
, sum(s."sum") OVER (PARTITION BY s."created_at", s."Category - name" ORDER BY s."created_at" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS "sum"
FROM (
SELECT date_trunc('month', "public"."stock_transaction"."created_at") AS "created_at", "Category"."name" AS "Category - name", sum("public"."stock_transaction"."cost") AS "sum"
FROM "public"."stock_transaction"
LEFT JOIN "public"."product" "Product" ON "public"."stock_transaction"."product_id" = "Product"."id"
LEFT JOIN "public"."category" "Category" ON "Product"."category_id" = "Category"."id"
WHERE ("public"."stock_transaction"."owner_id" = {{organization.id}}::uuid
AND {{createdAt}}
AND "Product"."recipe" = FALSE)
GROUP BY date_trunc('month', "public"."stock_transaction"."created_at"), "Category"."name"
-- ORDER BY date_trunc('month', "public"."stock_transaction"."created_at") ASC, "Category"."name" ASC -- not needed here
) AS s
ORDER BY s."created_at"

Multiple Sub Queries with Multiple JOINS Oracle

I have a large ORACLE SQL file with multi joins and multiple sub queries. I am having issues joining two of the sub queries. I have tried many different methods but the closest that I have gotten is below. The piece that is giving me trouble is the first portion of the join with the multiple subqueries (the Address Eff Date and the Employee Eff Date. The error message that I am receiving is ORA-00907: missing right parenthesis 00907. 00000 - "missing right parenthesis". I can't find where the right parenthesis is missing and I suspect it is more than that or some other type of syntax issue. The two tables that I have had trouble joinging are the EMPLOYEE_EFF_DATE table and the ADDRESS_EFF_DATE table. Both of these tables have an EFF_DATE field, and for both tables I need to pull the record with the most recent effective date (by SSN field). I believe I have accounted for that with the ROW_NUMBER() OVER (PARTITION method but if there is a more efficient or easier way to to this I am absolutely open to suggestions.
/*Subscriber Code*/
eed.P_COMPANY_ID_I as "Client Company ID"
,cs.REAL_SSN as "Employee SSN"
,cs.REAL_SSN as "Member SSN"
,'Subscriber' as "Person Type"
,eed.LAST_NAME as "Last Name"
,eed.FIRST_NAME as "First Name"
,eed.BIRTHDATE as "Date of Birth"
,eed.SEX as "Gender"
,aed.Address_1 as "Address 1"
,aed.Address_2 as "Address 2"
,aed.City
,aed.State
,aed.Zip
,aed.Country as "Country Code"
,aed.Telephone as "Employee Home Phone"
,eed.EMAIL_ADDRESS as "Employee Email Address"
,CASE
WHEN eed.controlled_group_status = 'L'
OR eed.controlled_group_status = 'P'
then eed.EFF_DATE
ELSE NULL
END
as "Date Last Actively At Work"
/*Remove line below*/
,eed.CONTROLLED_GROUP_STATUS
,CASE
WHEN eed.controlled_group_status = 'L'
OR eed.controlled_group_status = 'P'
then 'LEAVE'
ELSE NULL
END
as "Leave Status"
,CASE
WHEN eed.controlled_group_status = 'L'
OR eed.controlled_group_status = 'P'
then eed.EFF_DATE + 1
ELSE NULL
END
as "Leave Begin Date"
,eed.LATEST_HIRE_DATE as "Employee Date of Hire"
,eed.LAST_TERM_DATE as "Employee Date of Termination"
,mcemd.RATE_1 as "Employee Salary"
,ele.LIFE_EVENT_ID as "Life Event ID"
,ele.LIFE_EVENT_DATE as "Loss of Coverage Date"
FROM
/*Employee_Eff_Date*/
(SELECT *
FROM
(SELECT *
FROM
(SELECT eed1.*,
ROW_NUMBER() OVER (PARTITION BY eed1.SSN ORDER BY EFF_DATE DESC) as seqnum
FROM EMPLOYEE_EFF_DATE eed1)
WHERE seqnum = 1) eed)
JOIN
/*Address_Eff_Date*/
(SELECT *
FROM
(SELECT *
FROM
(SELECT aed1.*,
ROW_NUMBER() OVER (PARTITION BY aed1.SSN ORDER BY EFF_DATE DESC) as seqnum
FROM ADDRESS_EFF_DATE aed1
) aed1
ON aed1.SSN = eed.SSN
WHERE aed1.seqnum = 1) aed)
INNER JOIN COMPANY_EMPLOYMENT_DATA ced
ON eed.SSN = ced.SSN
INNER JOIN MV_COMB_EMP_MAX_DTS mcemd
ON eed.SSN = mcemd.SSN
INNER JOIN EMPLOYEE_LIFE_EVENTS ele
ON ele.SSN = eed.SSN
WHERE eed.P_COMPANY_ID_I = 1234
/*Address_Eff_Date qualifying statement*/
AND aed.ADDRESS_KEY = 0
/*EMPLOYEE_LIFE_EVENTS qualifying statement*/
/*Below line indicates the Life Event Dates (set to the past week)*/
AND ele.LIFE_EVENT_DATE >= sysdate-7
AND ele.LIFE_EVENT_DATE <= sysdate
I think you actually want this. Note you have more level of query nesting than you actually need and I have removed the extra ones:
/*Employee_Eff_Date*/
(SELECT *
FROM
(SELECT eed1.*,
ROW_NUMBER() OVER (PARTITION BY eed1.SSN ORDER BY EFF_DATE DESC) as seqnum
FROM EMPLOYEE_EFF_DATE eed1) eed1
WHERE seqnum = 1) eed
JOIN
/*Address_Eff_Date*/
(SELECT *
FROM
(SELECT aed1.*,
ROW_NUMBER() OVER (PARTITION BY aed1.SSN ORDER BY EFF_DATE DESC) as seqnum
FROM ADDRESS_EFF_DATE aed1
) aed1
WHERE aed1.seqnum = 1) aed ON aed.SSN = eed.SSN

Decode statement in SQL results in ORA-00936: missing expression

Trying to figure out why this decode isn't working. I just want to create a column that would separate the above line into <5 and >=5 and give them a corresponding answer. I really can't seem to see why it is not working, I keep getting ORA-00936: missing expression.
SELECT a.account_id "Account ID",
a.first_name ||' '|| a.last_name "Name",
b.date_and_time_created "Date Created",
c.date_and_time_ordered "Date Ordered",
c.date_and_time_ordered - b.date_and_time_created "Days Ordered After Created",
DECODE ((c.date_and_time_ordered - b.date_and_time_created), <5, 'No Reminder Needed',
>=5, 'Reminder Needed', ' ') "Reminder"
FROM shopper a
JOIN shopping_cart b ON a.account_id = b.shopper_account_id
JOIN orders c ON a.account_id = c.shopper_account_id
the problem causes due to usage of < > = within a decode statement , use this instead :
SELECT a.account_id "Account ID",
a.first_name ||' '|| a.last_name "Name",
b.date_and_time_created "Date Created",
c.date_and_time_ordered "Date Ordered",
c.date_and_time_ordered - b.date_and_time_created "Days Ordered After Created",
(case when ( c.date_and_time_ordered - b.date_and_time_created < 5 ) then 'No Reminder Needed'
when ( c.date_and_time_ordered - b.date_and_time_created >= 5 ) then 'Reminder Needed'
else ' '
end ) "Reminder"
FROM shopper a
JOIN shopping_cart b ON a.account_id = b.shopper_account_id
JOIN orders c ON a.account_id = c.shopper_account_id
Or, if you insist on DECODE (though, I don't know why would you want to do that as CASE is much more appropriate here), you could use SIGN function, such as
SELECT DECODE (
SIGN ( (c.date_and_time_ordered - b.date_and_time_created) - 5),
-1, 'less than 5',
'greater than or equal to 5')
result
FROM ...

sql to sum counts and add amounts from 2 tables

I am having getting the last sql to work.
The first two grouping gave me the right answer but the last one which involves joining 2 tables gave me a number thats too high when i manually add the first two together.
sql is to generate figures 1,2 and the (1+2) as 3.
Pls help.
sql below....
select [OrderDate] as "Date",
'Cobs' as "Payment Source",
COUNT(*) as "Quantity",
SUM([Amount]) as "Value in Pounds"
from cobaltins
where PN like 'BT%'
group by OrderDate
union all
select [OrderDate] as "Date",
'Cobs Adhoc' as "Payment Source",
COUNT(*) as "Quantity",
SUM([Amount]) as "Value in Pounds"
FROM cobaltins_adhoc
where name = 'Vauz'
group by OrderDate
union all
select cba.OrderDate as "Date",
'Cumulative' as "Payment Source",
COUNT(*) as "Quantity",
sum((cb.Amount)+(cba.Amount)) as "Value in Pounds"
FROM cobaltins as cb
left join cobaltins_adhoc as cba on cb.OrderDate = cba.OrderDate
where cb.PN like 'BT%'
or cba.name = 'Vauz'
group by cba.OrderDate
Rather than try and get it in one you might want to try and sum an inline view of your UNION
SELECT
"Date",
"Payment Source",
SUM(Quantity) Quantity,
SUM("Value in Pounds") "Value in Pounds"
FROM
(
select [OrderDate] as "Date",
'Cobs' as "Payment Source",
COUNT(*) as "Quantity",
SUM([Amount]) as "Value in Pounds"
from cobaltins
where PN like 'BT%'
group by OrderDate
union all
select [OrderDate] as "Date", '
Cobs Adhoc' as "Payment Source",COUNT(*) as "Quantity",
SUM([Amount]) as "Value in Pounds"
FROM cobaltins_adhoc
where name = 'Vauz'
group by OrderDate
) t
GROUP BY
"Date",
"Payment Source"
The way that you are doing your join
FROM cobaltins as cb
LEFT JOIN cobaltins_adhoc as cba
ON cb.OrderDate = cba.OrderDate
is only joining on the order date. if you have multiple orders per date then it's going to try to join those together arbitrarily. you will want to add something else into that join to make it distinct.
You are joining on OrderDate.
That means if there is more than one row in either table with the same order date, then you will get duplication of the matching rows in the other table.
A quick way to test this is to remove the COUNT(*) and the GROUP BY, and just look at the result of your join. Do you see any duplicates that you didn't want to count?
Why not do this with columns instead of rows?
select bt."Date", bt.Quantity as Cobs, vauz.Quantity as CobsAdhoc,
(bt.quantity + coalesce(vauz.Quantity)) as Total
from (select [OrderDate] as "Date", 'Cobs' as "Payment Source", COUNT(*) as "Quantity",
SUM([Amount]) as "Value in Pounds"
from cobaltins
where PN like 'BT%'
group by OrderDate
) bt left outer join
(select [OrderDate] as "Date", 'Cobs Adhoc' as "Payment Source",COUNT(*) as "Quantity",
SUM([Amount]) as "Value in Pounds"
FROM cobaltins_adhoc
where name = 'Vauz'
group by OrderDate
) vauz
on bt."Date" = vauz."Date";

Query on how to select data based on single condition

Need your help to review the below request.
i am using the below query and what i want to achieve is as below
i am trying to extract the min value of the new_status_id and not fetch any other details of any other status at all. Basically i am getting more than one line as output for one v_id that i input where as the desired output is one line and min(timestamp) to get fetched under column name Upload as defined below
Select
to_char(to_date(date,'DY Mon DD YYYY'),'MM-DD')||' '||Away_team.name||' '||'#'||' '||home_team.name as "Title",
video_jobs.id as "Job Id",
markets.name as "Market",
round as "Round",
to_char(to_date(date,'DY Mon DD YYYY'),'DD-Mon-YY') as "Date Aired",
competitions.name as "Competition",
Home_team.name as "Home Team",
Away_team.name as "Away Team",
job_statuses.name as "Job Status",
networks.name as "Network",
stadiums.name as "Stadium",
Round(images_count/3600.0,2) as "Footage Hours",
round(sum(minutes_in_logo_finder)/60.0,2) as "Logo Picker Time",
Round(sum(minutes_in_hits_editor)/60.0,2) as "Hits Editing Time",
Round(sum(minutes_in_branding)/60.0,2) as "Branding Time",
Round(sum(minutes_in_tagging)/60.0,2) as "Tagging Time",
Round(sum(minutes_in_qc)/60.0,2)as "QC Time",
Round(sum(minutes_in_idle)/60.0,2) as "Idle Time",
Round(sum(loading_time)/60.0,2) as "Loading Time",
Round(sum(minutes_in_logo_finder+minutes_in_hits_editor + minutes_in_branding +minutes_in_tagging +minutes_in_qc+minutes_in_idle+loading_time)/60.0,2) as "Total"
from video_jobs
Join markets on video_jobs.market_id = markets.id
Join stadiums on video_jobs.stadium_id = Stadiums.id
Join job_statuses on video_jobs.status_id = job_statuses.id
Join competitions on video_jobs.competition_id = competitions.id
Join networks on video_jobs.network_id = networks.id
Join sessions on video_jobs.id = sessions.job_id
join teams as Home_team on video_jobs.home_team_id = home_team.id
join teams as Away_team on video_jobs.away_team_id = Away_team.id
Join video_job_status_history on video_jobs.id = video_job_status_history.video_job_id
Where video_jobs.id > 163026
group by
video_jobs.id,
markets.name,
video_jobs.round,
stadiums.name,
job_statuses.name,
competitions.name,
networks.name,
video_jobs.images_count,
home_team.name,
Away_team.name,
video_jobs.date
order by
video_jobs.id
Add the condition into the where clause:
select min(timestamp) as "Uplaod"
from v_jobs
where v_id = 1234 and new_status_id = 25;
EDIT:
In that case, what you want is conditional aggregation:
select min(case when new_status_id = 25 then timestamp end) as MinTimestamp25
. . .