Joining multiple sum sql statements - sql

How can I join multiple sql statements. I need to display in one view respectively 2004,2008,2009 and so on
SELECT SUM(ACQUISITIONPRICE) AS YEAR_2007
FROM TRANS
WHERE DATEACQUIRED LIKE '%07';
SELECT SUM(ACQUISITIONPRICE) AS YEAR_2008
FROM TRANS
WHERE DATEACQUIRED LIKE '%08';
SELECT SUM(ACQUISITIONPRICE) AS YEAR_2009
FROM TRANS
WHERE DATEACQUIRED LIKE '%09';

check this sql fiddle
I have handled your requirement with case statement which seems to be very easy.
SELECT SUM(ACQUISITIONPRICE) AS TOTALPRICE
, EXTRACT(year from DATEACQUIRED) AS YEAR
FROM TRANS
GROUP BY EXTRACT(year from DATEACQUIRED)
ORDER BY YEAR;
SELECT Sum(CASE
WHEN Extract(year FROM dateacquired) = 2007 THEN acquisitionprice
ELSE 0
END) AS YEAR_2007,
Sum(CASE
WHEN Extract(year FROM dateacquired) = 2008 THEN acquisitionprice
ELSE 0
END) AS YEAR_2008,
Sum(CASE
WHEN Extract(year FROM dateacquired) = 2009 THEN acquisitionprice
ELSE 0
END) AS YEAR_2009
FROM trans

Just use GROUP BY like so:
SELECT SUM(ACQUISITIONPRICE) AS TOTALPRICE
, EXTRACT(year from DATEACQUIRED) AS YEAR
FROM TRANS
GROUP BY EXTRACT(year from DATEACQUIRED)
ORDER BY YEAR
If you really want to "join" them all in one row, with specific column names, you can do the following (though this approach is less flexible, since the query will have to be manually modified every year). Also note that although the question specifically mentioned "joining" the results, the join as shown below is completely unnecessary. Each column could simply be part of the select clause without any join. (here is the SqlFiddle)
SELECT * FROM
(SELECT SUM(ACQUISITIONPRICE) AS YEAR_2007
FROM TRANS
WHERE EXTRACT(year from DATEACQUIRED) = 2007) a
JOIN
(SELECT SUM(ACQUISITIONPRICE) AS YEAR_2008
FROM TRANS
WHERE EXTRACT(year from DATEACQUIRED) = 2008) b ON 1=1
JOIN
(SELECT SUM(ACQUISITIONPRICE) AS YEAR_2009
FROM TRANS
WHERE EXTRACT(year from DATEACQUIRED) = 2009) c ON 1=1
If you want the results in a single row, a preferable approach is to use a sub-select with dual as shown in this fiddle:
SELECT
(SELECT SUM(ACQUISITIONPRICE) FROM TRANS WHERE EXTRACT(year from DATEACQUIRED) = 2007) AS YEAR_2007
, (SELECT SUM(ACQUISITIONPRICE) FROM TRANS WHERE EXTRACT(year from DATEACQUIRED) = 2008) AS YEAR_2008
, (SELECT SUM(ACQUISITIONPRICE) FROM TRANS WHERE EXTRACT(year from DATEACQUIRED) = 2009) AS YEAR_2009
FROM dual
When it comes to performance, the only real way to be sure is of course to test it in your particular scenario, but the SUM (CASE... approach shown by #Indra-Prakash-Tiwari may perform better in most cases (if oracle behaves anything like sql server)

Try Use To_Char
Fiddle demo
select TO_CHAR(DATEACQUIRED,'yy') AS Years_Char,Sum(ACQUISITIONPRICE)
FROM trans GROUP BY TO_CHAR(DATEACQUIRED,'yy')

Related

Trying to join two tables via subquery

Current query below
select
x.OVERALL_ID,
extract(year from y.tsdate) as year,
extract(month from y.tsdate) as month,
round(sum(y.grossamount),2) as "labour cost",
sum(y.reg)+sum(y.ot) as "labour hours"
from
(
select OVERALL_ID,
BOAT_NAME
from TV_VESSEL_VISIT
group by OVERALL_ID,VESSEL_NAME
order by OVERALL_ID, VESSEL_NAME
) as x
inner join
(
select *
from TRANS
where ratedesc = 'Labour'
and opsdesc = 'Ops'
and ACTDESC = 'Nature of Job'
and terminal = 'UKN'
and reconciled = 'Y'
and TSDATE between '20-JAN-01' and '20-JAN-31'
) as y on x.BOAT_NAME = y.BOATNAME
group by OVERALL_ID, extract(year from tsdate), extract(month from tsdate)
order by OVERALL_ID, extract(year from tsdate), extract(month from tsdate);
Desired result is OVERALL_ID's labour cost/hours grouped into year and month
Currently getting the below error
ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
*Cause:
*Action:
Error at Line: 14 Column: 3
Trying to follow this link https://www.geeksengine.com/database/subquery/subquery-in-join-operation.php
Orable allows AS when declaring a column alias, but does not allow it for a table alias. The subquery alias is the same case as table alias. try ) x instead of ) as x, and the same thing for y. This is one of the syntax errors that causes ORA-00933.
If using subqueries DO NOT use ORDER BY inside those subqueries. There is no good purpose to the ordering, it just isn't required.
Try this:
SELECT
x.OVERALL_ID
, extract(year FROM y.tsdate) AS year
, extract(month FROM y.tsdate) AS month
, round(sum(y.grossamount), 2) AS "labour cost"
, sum(y.reg) + sum(y.ot) AS "labour hours"
FROM (
SELECT DISTINCT
OVERALL_ID
, BOAT_NAME
FROM TV_VESSEL_VISIT
) x
INNER JOIN (
SELECT *
FROM TRANS
WHERE ratedesc = 'Labour'
AND opsdesc = 'Ops'
AND ACTDESC = 'Nature of Job'
AND terminal = 'UKN'
AND reconciled = 'Y'
AND TSDATE >= to_date('2020-01-01','yyy-mm-dd') AND TSDATE < to_date('2020-02-01','yyyy-mm-dd')
) y ON x.BOAT_NAME = y.BOATNAME
GROUP BY
OVERALL_ID
, extract(year FROM tsdate)
, extract(month FROM tsdate)
ORDER BY
OVERALL_ID
, extract(year FROM tsdate)
, extract(month FROM tsdate)
;
Notes: I have removed the unwanted ORDER BY in the upper subquery, and changed this to use SELECT DISTINCT (it will produce the same result as the previous group by subquery). Also I have changed the syntax used for the date range. Please avoid using 2 digit year references, always use the full year. Additionally I always recommend avoiding the use of between for date ranges it is far more predictable to use the combination of >= with < as you see above. Plus I have used to_date() so it is clear what dates I am using for the date range - which will give you every row of data relevant to January 2020.
The previous between syntax could possibly miss a whole day's data

Select count inner join two database

I want to show all supplier information sorted by country, including number of names supplied in current month.
Here are the two database and their variables:
1.Supplier: SupplierID, Suppliedname, Country, ReliabilityScore, ContactInfo
2.SuppliedName: SnID, Suppliedname1, Language, Status, Standard, PlaceID,SupplierID, Supplieddate
Here's what I came up with which didn't really work:
SELECT COUNT(DISTINCT SuppliedName.suppliedname1), Supplier.(*) FROM SuppliedName
INNER JOIN Supplier ON Supplier.SupplierID = SuppliedName.SupplierID
WHERE EXTRACT(MONTH FROM SuppliedName.Supplieddate)=EXTRACT(MONTH FROM sysdate) AND EXTRACT(YEAR FROM SuppliedName.Supplieddate)=EXTRACT(YEAR FROM sysdate)
ORDER BY Supplier.Country;
Please help!!! Thanks!
I guess you just missed to GROUP BY all columns from SUPPLIER.
SELECT COUNT(DISTINCT SUPPLIEDNAME.SUPPLIEDNAME1),
SUPPLIER.SUPPLIERID,
SUPPLIER.SUPPLIEDNAME,
SUPPLIER.COUNTRY,
SUPPLIER.RELIABILITYSCORE,
SUPPLIER.CONTACTINFO
FROM SUPPLIEDNAME
INNER JOIN SUPPLIER
ON SUPPLIER.SUPPLIERID = SUPPLIEDNAME.SUPPLIERID
WHERE EXTRACT(MONTH FROM SUPPLIEDNAME.SUPPLIEDDATE) = EXTRACT(MONTH FROM SYSDATE)
AND EXTRACT(YEAR FROM SUPPLIEDNAME.SUPPLIEDDATE) = EXTRACT(YEAR FROM SYSDATE)
GROUP BY SUPPLIER.SUPPLIERID,
SUPPLIER.SUPPLIEDNAME,
SUPPLIER.COUNTRY,
SUPPLIER.RELIABILITYSCORE,
SUPPLIER.CONTACTINFO
ORDER BY SUPPLIER.COUNTRY;

Not Exists query

I'm trying to find the clients, those who didn't order in the last 2 years and they ordered this year more than 500.. I wrote this query and I used the "NOT EXISTS" condition, but it is still showing me the wrong results.
Some suggestions would be appreciated.
My code:
SELECT
"Sales"."Kundennummer" as 'Neuer Kunde',
year("Sales"."Datum"),
sum("Sales"."Umsatz mit Steuer") as "Umsatz"
FROM "Sales"
WHERE year("Sales"."Datum") = '2017'
AND NOT EXISTS
(
SELECT "Sales"."Kundennummer"
FROM "Sales"
WHERE year("Sales"."Datum") = '2015'
AND year("Sales"."Datum") = '2016'
)
GROUP BY
"Sales"."Kundennummer",
"Sales"."Datum"
HAVING sum("Sales"."Umsatz mit Steuer") > 500
The query in the NOT EXISTS clause will probably yield 0 rows, since a row can't have Datum both 2015 and 2016. So it should probably be OR instead of AND.
Also, if you fix this, there is no link between the subquery and the superquery, which means that it will return rows for any customer (given that there exists a row with Datum either 2015 or 2016 in your table which I guess it does).
So, something like:
SELECT
"Sales"."Kundennummer" as 'Neuer Kunde',
year("Sales"."Datum"),
sum("Sales"."Umsatz mit Steuer") as "Umsatz"
FROM "Sales" sales
WHERE year("Sales"."Datum") = '2017'
AND NOT EXISTS
(
SELECT "Sales"."Kundennummer"
FROM "Sales" salesI
WHERE salesI."Kundennummer" = sales."Kundennummer"
AND (year("Sales"."Datum") = '2015'
OR year("Sales"."Datum") = '2016')
)
GROUP BY
"Sales"."Kundennummer",
"Sales"."Datum"
HAVING sum("Sales"."Umsatz mit Steuer") > 500
Your EXISTS query is not correlated to the main query, i.e. it doesn't look for data for the Kundennummer in question, but whether there are any records in 2015 and 2016.
(You also have the condition for the years wrong by using AND where it must be OR and you should not use quotes on numbers like 2015', and you should not use single quotes on names like 'Neuer Kunde'.)
It should be
AND NOT EXISTS
(
SELECT *
FROM Sales other_years
WHERE other_years.Kundennummer = Sales.Kundennummer
AND year(other_years.Datum) in (2015, 2016)
)
or uncorrelated with NOT IN
AND Kundennummer NOT IN
(
SELECT Kundennummer
FROM Sales
WHERE year(Datum) in (2015, 2016)
)
Be aware though, that when using NOT IN the subquery must return no nulls. E.g. where 3 not in (1, 2, null) does not result in true, as one might expect, because the DBMS argues that the unknown value (null) might very well be a 3 :-)
I propose you here below 3 different ways to do it:
Joining 2 tables
select this_year_sales.kundenummer, this_year_sales.tot_umsatz
from (select sum(umsatz) tot_umsatz, kundenummer from sales where extract(year from (datum)) = extract(year from sysdate) group by kundenummer) this_year_sales
, (select kundenummer, max(datum) max_datum from sales where datum < trunc(sysdate, 'year') group by kundenummer) previous_sales
where this_year_sales.kundenummer = previous_sales.kundenummer
and extract(year from previous_sales.max_datum) < (extract(year from sysdate)-2)
and this_year_sales.tot_umsatz > 500;
Using NOT INT
select kundenummer, sum(umsatz)
from sales s
where extract(year from datum) = extract(year from sysdate)
and kundenummer not in (select kundenummer from sales where extract(year from datum) > (extract(year from sysdate) - 2) and extract(year from datum) < (extract(year from sysdate)-1))
group by kundenummer
having sum(umsatz) > 500;
Using NOT EXISTS
select kundenummer, sum(umsatz)
from sales s
where extract(year from datum) = extract(year from sysdate)
and not exists(
select s1.kundenummer, s1.datum from sales s1 where extract (year from s1.datum) >= (extract(year from sysdate)-2) and extract(year from s1.datum) < extract (year from sysdate) and s1.kundenummer = s.kundenummer
)
group by kundenummer
having sum(umsatz) > 500;

how to return total sold p / year for several years in columnar format?

The SQL below give me the columns for Account, Name and the Total Sale for the year of 2015.But how, if possible, can I add another column for the previous year of 2014 ?
select a.AcctNo, b.Name, Sum(a.TotSold) as [ Total Sold ]
from Orders as A
Join Accounts as b on a.AcctNo = b.AcctNo
where (a.PurchaseDate between '1/1/2015' and '12/31/2015' )
Group by a.AcctNo, b.Name
You can use conditional aggregation:
select o.AcctNo, a.Name,
Sum(case when year(PurchaseDate) = 2015 then TotSold else 0 end) as tot_2015,
Sum(case when year(PurchaseDate) = 2014 then TotSold else 0 end) as tot_2014
from Orders o Join
Accounts a
on a.AcctNo = o.AcctNo
where PurchaseDate >= '2014-01-01'
PurchaseDate < '2016-01-01'
Group by o.AcctNo, a.Name ;
Notes:
Use ISO standard formats for date constants.
When using dates, try not to use between. It doesn't work as expected when there is a time component. The above inequalities work regardless of a time component.
Use table aliases that are abbreviations of the table name. That makes the query easier to follow.

Odd 'GROUP BY' error in a sub-query while using Oracle

A quick background -- I need to find the termination rates of cases that go through our company lab grouped by case type and month. So far I came up with this:
SELECT BPI.TYPE,
EXTRACT(MONTH FROM CS.RECEIVED_DATE) MONTH,
COUNT(*) termed_cases
FROM CELL_SOURCE cs
JOIN BASIC_PATHOLOGY_INFO bpi ON CS.CELL_SOURCE_ID = BPI.CELL_SOURCE_ID
JOIN RECENT_CELL_SOURCE_STATUS rcss ON CS.CELL_SOURCE_ID = RCSS.CELL_SOURCE_ID
WHERE type IS NOT NULL
AND CS.RECEIVED_DATE > to_date('03/01/2011', 'MM/DD/YYYY/')
AND RCSS.STATUS like 'Term%'
GROUP BY BPI.TYPE, EXTRACT(MONTH FROM CS.RECEIVED_DATE)
ORDER BY month, type
This finds all cases that have been termed, easy enough. However, when I want to find the rate, I get a bit of a problem. I tried using a sub-query to catch the total amount of cases per type regardless of it's status, as such:
COUNT(*)/(SELECT COUNT(*)
FROM CELL_SOURCE cs_1
JOIN BASIC_PATHOLOGY_INFO bpi_1 ON CS_1.CELL_SOURCE_ID = BPI_1.CELL_SOURCE_ID
WHERE BPI_1.TYPE = BPI.TYPE
AND EXTRACT(month from CS_1.RECEIVED_DATE) = EXTRACT(MONTH FROM CS.RECEIVED_DATE)) termed_cases
However, this throws an ORA-00979: not a GROUP BY expression error, and highlights BPI.TYPE from the sub-query.
Anyone have any idea what my error could actually be? Also, would an analytical function work better here than an aggregate function?
So, you need two counts: a total for all cases in the month and a total for just the Termed cases. The easiest way of doing this is to use a CASE() function to execute a conditional count, like this:
SELECT BPI.TYPE,
EXTRACT(MONTH FROM CS.RECEIVED_DATE) MONTH,
COUNT(*) all_cases,
sum(case when RCSS.STATUS like 'Term%' then 1 else 0 end ) termed_cases
FROM CELL_SOURCE cs
JOIN BASIC_PATHOLOGY_INFO bpi ON CS.CELL_SOURCE_ID = BPI.CELL_SOURCE_ID
JOIN RECENT_CELL_SOURCE_STATUS rcss ON CS.CELL_SOURCE_ID = RCSS.CELL_SOURCE_ID
WHERE tumor_type IS NOT NULL
AND CS.RECEIVED_DATE > to_date('03/01/2011', 'MM/DD/YYYY/')
GROUP BY BPI.TUMOR_TYPE, EXTRACT(MONTH FROM CS.RECEIVED_DATE)
ORDER BY month, tumor_type
Note that I have removed the LIKE filter from the WHERE clause.
select bpi.type , month,
termed_cases /
(select count(*)
from CELL_SOURCE cs_1
inner join BASIC_PATHOLOGY_INFO bpi_1
on CS_1.CELL_SOURCE_ID = BPI_1.CELL_SOURCE_ID
where BPI_1.TUMOR_TYPE = BPI.TUMOR_TYPE
and extract(month from CS_1.RECEIVED_DATE) = extract(MONTH FROM CS.RECEIVED_DATE)
)
from (
select BPI.TYPE,
extract(MONTH FROM CS.RECEIVED_DATE) MONTH,
count(*) termed_cases
from CELL_SOURCE cs
inner join BASIC_PATHOLOGY_INFO bpi
on CS.CELL_SOURCE_ID = BPI.CELL_SOURCE_ID
inner join RECENT_CELL_SOURCE_STATUS rcss
on CS.CELL_SOURCE_ID = RCSS.CELL_SOURCE_ID
where tumor_type is not null
and CS.RECEIVED_DATE > to_date('03/01/2011', 'MM/DD/YYYY/')
and RCSS.STATUS like 'Term%'
group by BPI.TYPE, extract(MONTH FROM CS.RECEIVED_DATE)
)
order by month, type