I have a litte problem here. I want to join twice from the same table, and group by a common value.
Here is the dataset (from table Voucher):
Date (dd/mm/yyyy) Amount
--------------------------
01.01.2010 1.000
15.01.2010 2.000
01.03.2010 3.000
01.03.2010 4.000
01.05.2010 5.000
01.01.2011 1.000
01.02.2011 2.000
01.04.2011 3.000
15.04.2011 4.000
01.05.2011 5.000
The result should be like this:
Month Amount 2010 Amount 2011
---------------------------------
1 3.000 1.000
2 2.000
3 7.000
4 7.000
5 5.000 5.000
How do I solve this?
Something along these lines will work for this case:
SELECT
DATEPART(month,[Date]) as Month,
SUM(CASE WHEN DATEPART(year,[Date]) = 2010 THEN Amount END) as [Amount 2010],
SUM(CASE WHEN DATEPART(year,[Date]) = 2011 THEN Amount END) as [Amount 2011]
FROM
Voucher
GROUP BY
DATEPART(month,[Date]) as Month
For other situations, you might want to look into PIVOT.
Date is a really poor name for a column.
You have to give the tables different names like in this example:
SELECT Fruit1, F1FruitName = F1.FruitName, F1FruitCost = F1.FruitCost,
Fruit2, F2FruitName = F2.FruitName, F2FruitCost = F2.FruitCost FROM T1
JOIN T2 F1 ON Fruit1 = F1.Fruit_ID
JOIN T2 F2 ON Fruit2 = F2.Fruit_ID
The concrete syntax depends on your database system.
Related
Table A
date
flight
airport
2012-10-01
oneway
ATL, GA
2012-10-01
oneway
LAX, CA
2012-10-02
oneway
SAN, CA
2012-10-02
oneway
DTW, MI
2012-10-03
round
SFO, CA
2012-10-04
round
SFO, CA
2012-10-05
round
SFO, CA
Table B
date
temp
precip
2012-10-01
27
0.02
2012-10-02
35
0.00
2012-10-03
66
0.18
2012-10-04
57
0.00
2012-10-05
78
0.24
Table A has about 100k rows and whereas Table B has only about 60 rows
I am trying to query to find total number of flights on cold days and warm days as well as tracking the number of days for either cold or warm.
A cold day is defined when temp from Table B is below (<) 40 and warm otherwise.
In the real data, I have total 10 days that matches the date therefore I need to count for that when aggregating. I tried to get the total count without using CTE but I am keep getting wrong counts.
The expected outcome
Days
Num_of_flight
Num_of_days
cold day
4
2
warm day
3
3
You need a LEFT join of TableB to TableA and aggregation on the result of a CASE expression which returns 'cold' or 'warm':
SELECT CASE WHEN b.temp < 40 THEN 'cold day' ELSE 'warm day' END Days,
COUNT(*) Num_of_flight,
COUNT(DISTINCT a.date) Num_of_days
FROM TableB b LEFT JOIN TableA a
ON a.date = b.date
GROUP BY Days;
See the demo.
I am using Firebird 3, and have 2 tables: Income and Expenses, each table has a VatAmount and a Date field.
I want to merge this 2 tables in a query, avoid duplicate values and set a filter range between month dates, to get a result like this:
Month
Income VatAmount
Expenses VatAmount
Difference
Jan
1.000
500
500
Feb
3.000
1.000
2.000
Mar
700
2.000
1.300
I have been searching for a solution, but no luck so far.
I am dealing with a sales order table (ORDER) that looks roughly like this (updated 2018/12/20 to be closer to my actual data set):
SOID SOLINEID INVOICEDATE SALESAMOUNT AC
5 1 2018-11-30 100.00 01
5 2 2018-12-05 50.00 02
4 1 2018-12-12 25.00 17
3 1 2017-12-31 75.00 03
3 2 2018-01-03 25.00 05
2 1 2017-11-25 100.00 17
2 2 2017-11-27 35.00 03
1 1 2017-11-20 15.00 08
1 2 2018-03-15 30.00 17
1 3 2018-04-03 200.00 05
I'm able to calculate the average sales by SOID and SOLINEID:
SELECT SUM(SALESAMOUNT) / COUNT(DISTINCT SOID) AS 'Total Sales per Order ($)',
SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM ORDER
This seems to provide a perfectly good answer, but I was then given an additional constraint, that this count be done by year and month. I thought I could simply add
GROUP BY YEAR(INVOICEDATE), MONTH(MONTH)
But this aggregates the SOID and then performs the COUNT(DISTINCT SOID). This becomes a problem with SOIDs that appears across multiple months, which is fairly common since we invoice upon shipment.
I want to get something like this:
Year Month Total Sales Per Order Total Sales Per Line
2018 11 0.00
The sore thumb sticking out is that I need some way of defining in which month and year an SOID will be aggregated if it spans across multiple ones; for that purpose, I'd use MAX(INVOICEDATE).
From there, however, I'm just not sure how to tackle this. WITH? A subquery? Something else? I would appreciate any help, even if it's just pointing in the right direction.
You should select Year() and month() for invocedate and group by
SELECT YEAR(INVOICEDATE) year
, MONTH(INVOICEDATE) month
, SUM(SALESAMOUNT) / COUNT(DISTINCT SOID) AS 'Total Sales per Order ($)'
, SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM ORDER
GROUP BY YEAR(INVOICEDATE), MONTH(INVOICEDATE)
Here are the results, but the data sample does not have enuf rows to show Months...
SELECT
mDateYYYY,
mDateMM,
SUM(SALESAMOUNT) / COUNT(DISTINCT t1.SOID) AS 'Total Sales per Order ($)',
SUM(SALESAMOUNT) / COUNT(SOLINEID) AS 'Total Sales per Line ($)'
FROM DCORDER as t1
left join
(Select
SOID
,Year(max(INVOICEDATE)) as mDateYYYY
,Month(max(INVOICEDATE)) as mDateMM
From DCOrder
Group By SOID
) as t2
On t1.SOID = t2.SOID
Group by mDateYYYY, mDateMM
mDateYYYY mDateMM Total Sales per Order ($) Total Sales per Line ($)
2018 12 87.50 58.33
I have used new SQL still MAX(INVOICEDATE)(not above), with new 12/20 data, and excluded AC=17.
YYYY MM Total Sales per Order ($) Total Sales per Line ($)
2017 11 35.00 35.00
2018 1 100.00 50.00
2018 4 215.00 107.50
2018 12 150.00 75.00
I apologize for the confusing title. I am dealing with an issue this morning that I thought I solved with everyone's help here but I can't do what I originally had hoped with just the master_line_num. Once again, below is a small subset of the data I am working with:
ID Proj_Id Year Quarter Value **Cumu_Value** Master_Line_Num
1 "C102" 2017 1 200.00 **200.00** 1
2 "C102" 2017 2 200.00 **400.00** 2
3 "C102" 2017 3 200.00 **600.00** 3
4 "C102" 2017 4 200.00 **800.00** 4
5 "C102" 2018 1 400.00 **1200.00** 5
6 "C102" 2018 2 400.00 **1600.00** 6
7 "C102" 2018 3 400.00 **2000.00** 7
8 "C102" 2018 4 400.00 **2400.00** 8
9 "B123" 2017 1 100.00 **100.00** 1
10 "B123" 2017 2 100.00 **200.00** 2
11 "B123" 2017 3 100.00 **300.00** 3
12 "B123" 2017 4 100.00 **400.00** 4
13 "B123" 2018 1 200.00 **600.00** 5
14 "B123" 2018 2 200.00 **800.00** 6
15 "B123" 2018 3 200.00 **1000.00** 7
16 "B123" 2018 4 200.00 **1200.00** 8
The desired values I am trying to get is the "Cumu_Value" column. I am trying to get those values by adding up the "value" column by year, by quarter for a specific "Proj_Id". I originally just tried to multiply the "value" column by the master_line_num column after getting that but then realized that it doesn't work due to the "value" column changing between years.
Is it possible to calculate this with T-SQL or do I need to do something more extravagant?
SQL supports the cumulative sum as a window function, so this is easy to express:
select . . . ,
sum(value) over (partition by proj_id order by year, quarter) as cumulative_sum
You need a Windowed Aggregate, this will return a Cumulative Sum:
sum(value)
over (partition by proj_id
order by Year, Quarter
rows unbounded preceding)
Caution, don't use (partition by proj_id order by Year, Quarter) without the ROWS as it defaults to RANGE which might return a different result and has much more overhead. RANGE includes all rows with the same value as the current. In your case it would return:
800
800
800
800
2400
2400
2400
2400
Edit:
After checking your other question I noticed that you don't have a Master_Line_Num in your data, so you better use ORDER BY Year, Quarter instead.
You can try something like this:
select t1.id, t1.proj_ID, t1.Year, t1.Value, SUM(t2.Value) as Cumu_sum, Master_Line_Num
from #tablename t1
inner join #tablename t2 on t1.id >= t2.id
group by t1.id, t1.Value
order by t1.id
I have a table, the data in it looks similar to this:
user type hours used --to make another column with this info available
2334 sick 10.000 2.000 8.000
2334 vacation 48.000 56.000 -8.000
2334 personal 0 8.000 0
1356 sick 0 16.000 -16.000
1356 vacation 80.000 0 80.000
1356 personal 14.000 14.000 0
4355 sick 4.000 1.000 3.000
4355 vacation 112.000 0 112.000
4355 personal 8.000 0 8.000
I had to sum up the values in the hours column, but only for each user. So user 2334 would have earned 58.000 hours, 10.000 + 48.000 + 0 but would have used 66.000 hours resulting in -8.000 hours.
SELECT user, SUM(hours) totalHours
FROM tableName
GROUP BY user
SEE SQLFiddle Demo