I am trying to use a UNION to append the total column in the first top half to the second half of the query.
SELECT NULL as month, NULL as active, count(cage_player_id) as total
FROM player_signup as p
GROUP BY date_part('month', p.signup_date)
UNION
SELECT date_part('month', signup_date) as month, count(DISTINCT(p.cage_player_id)) as active, NULL as total
FROM player_signup as p
JOIN daily_kpis as d ON p.cage_player_id = d.cage_player_id
WHERE slot_bet_amount > 0
OR ld_bet_amount > 0
OR table_bet_amount > 0
GROUP BY date_part('month', p.signup_date)
ORDER BY date_part('month', p.signup_date) ASC
I keep getting an error that says the FROM clause is missing for table p. Can anyone help? Is there an easier way to combine these two queries?
Here is what each query looks like separately. I just want to add the total column right next to the month and active column. The total ID's would still be broken down by months.
Query 1
Query 2
The problem is the order by clause. It applies to the results of the union query, so it cannot see the identifiers that are defined within the queries. Instead, you should use the names of the column in the resultset.
So you want to change this:
ORDER BY date_part('month', p.signup_date) ASC
To:
ORDER BY month
I believe this is the query you need:
SELECT date_part('month', signup_date) as month
, count(DISTINCT(p.cage_player_id)) as active
, (select count(cage_player_id)
FROM player_signup as p
GROUP BY date_part('month', p.signup_date)) as total
FROM player_signup as p
JOIN daily_kpis as d ON p.cage_player_id = d.cage_player_id
WHERE slot_bet_amount > 0
OR ld_bet_amount > 0
OR table_bet_amount > 0
GROUP BY date_part('month', p.signup_date)
ORDER BY date_part('month', p.signup_date) asc
I am not so good at Postgresql, please try this:
SELECT date_part('month', signup_date) as month
, count(DISTINCT(p.cage_player_id)) as active
, max(t1.total) as total
FROM player_signup as p
left join (select count(pp.cage_player_id) over (partition by date_part('month', pp.signup_date)) as total
, date_part('month', pp.signup_date) date_p
FROM player_signup as pp) t1 on t1.date_p = date_part('month', p.signup_date)
JOIN daily_kpis as d ON p.cage_player_id = d.cage_player_id
WHERE slot_bet_amount > 0
OR ld_bet_amount > 0
OR table_bet_amount > 0
GROUP BY date_part('month', p.signup_date)
ORDER BY date_part('month', p.signup_date)
Related
I have the following two queries that I need to join together to get one final output.
The primary keys are year, month,cost_center, g.account, and e.submapping.
The first table is an acutals table from a GL while the second query is a planned amount. I am trying to compare actuals to plan and need to join these two tables with the primary keys listed.
---Query 1 (e)
with Ranking as (
select c.*, rank() over(partition by
c.ledger_name,
c.company_code,
c.location_code,
c.cost_center,
c.account_number,
c.period_name,
c.currency,
c.amount,
c.entered_amount,
c.dm_insert_dt
order by dw_last_updated DESC) rnk
from wbr_global.gl_ap_details c
where cost_center IN ('1168','1153','1172','1257')
and ledger_name IN ('ABC.com, Inc.')
and account_number between '59999' and '70000')
select
to_date(period_name, 'Mon-YY') as BalanceDate,
date_part(month,(to_date(period_name, 'Mon-YY'))) as Months,
Case
when right(period_name,2) = right(date_part_year(current_date),2) then 'Current Year'
when right(period_name,2) = right(date_part_year(current_date) - 1,2) then 'Prior Year'
else 'Error' end as YearFlag,
EXTRACT(YEAR from balancedate) as year,
EXTRACT(Month from balancedate) as month,
e.sub_mapping,
c.cost_center,
c.period_name,
sum(c.amount) as amount
from Ranking c
left join wbr_global.raw_station_extended_attribute d on c.location_code = d.location_code
left join sandbox.utr_fixed_mapping_na e on c.account_number = e.account_number
where c.cost_center IN ('1168','1153','1172','1257')
and c.ledger_name = 'abc.com, Inc.'
and c.rnk = 1
group by 1,2,3,4,5,6,7,8
limit 10
Here is the second query
---Second query g
EXTRACT(YEAR from first_day_of_month) as year,
EXTRACT(Month from first_day_of_month) as month,
first_day_of_month,country,cost_center,scenario,'employee_relation' as account,
sum(employee_relation) as amount
from prophecy_to_sabre_ds_db.prophecy_caffeine.output_ww_field_opex
where cost_center = 1172
AND scenario = 'Q2G_22_1'
group by 1,2,3,4,5,6
Would I be able to make one a sub query in the other and join that way.
(Query 2) as g on g.cost_center = c.cost_center
and g.account = e.sub_mapping
and g.year = e.year
and g.month = e.month
I would like to make a query that will show me the total count and sum of sales, and for 2 workers in the same rows.
When I'm not using group by in a subquery I get a count for total sales for this worker not counted for each month. But when I try to use Group By clause in a subquery it shows me this error:
PG::CardinalityViolation:
ERROR: more than one row returned by a subquery used as an expression
And that makes sense but how I can count and sum amount of sales per month for each worker? Is there any possibility of transferring the value of Group By clause from query to a subquery? Should I be using subquery for this specific issue or maybe I can somehow make it easier?
SELECT
DATE_PART('month', payment_date) as month,
COUNT(payment_id) AS total_count,
SUM(amount) AS total_amount,
(SELECT COUNT(payment_id)
FROM payment
WHERE staff_id = 1
GROUP BY DATE_PART('month', payment_date)) AS mike_count,
(SELECT SUM(amount)
FROM payment
WHERE staff_id = 1
GROUP BY DATE_PART('month', payment_date)) AS mike_amount,
(SELECT COUNT(payment_id)
FROM payment
WHERE staff_id = 2
GROUP BY DATE_PART('month', payment_date)) AS jon_count,
(SELECT SUM(amount)
FROM payment
WHERE staff_id = 2
GROUP BY DATE_PART('month', payment_date)) AS jon_amount
FROM
payment
GROUP BY
DATE_PART('month', payment_date)
ORDER BY
DATE_PART('month', payment_date);
This is the outcome w/o the group by clause in subqueries:
month |total_count |total_amount |mike_count |mike_amount |jon_count |jon_amount
2 |2016 |0.835184E4 |7292 |0.3025212E5 |7304 |0.3105992E5
3 |5644 |0.2388656E5 |7292 |0.3025212E5 |7304 |0.3105992E5
4 |6754 |0.2855946E5 |7292 |0.3025212E5 |7304 |0.3105992E5
5 |182 |0.51418E3 |7292 |0.3025212E5 |7304 |0.3105992E5
Use conditional aggregation instead:
SELECT DATE_PART('month', payment_date) as month,
count(payment_id) AS total_count,
SUM(amount) AS total_amount,
SUM(CASE WHEN staff_id = 1 THEN 1 ELSE 0 END) as mike_count,
SUM(CASE WHEN staff_id = 1 THEN amount ELSE 0 END) as mike_amount,
SUM(CASE WHEN staff_id = 2 THEN 1 ELSE 0 END) as jon_count,
SUM(CASE WHEN staff_id = 2 THEN amount ELSE 0 END) as jon_amount
FROM payment
GROUP BY DATE_PART('month', payment_date)
ORDER BY DATE_PART('month', payment_date);
DATE_PART() suggests that you are using Postgres. If so, I would recommend the FILTER clause:
SELECT DATE_PART('month', payment_date) as month,
COUNT(payment_id) AS total_count,
SUM(amount) AS total_amount,
COUNT(*) FILTER (WHERE staff_id = 1) as mike_count,
SUM(amount) FILTER (WHERE staff_id = 1) as mike_amount,
COUNT(*) FILTER (WHERE staff_id = 2) as jon_count,
SUM(amount) FILTER (WHERE staff_id = 2) as jon_amount
FROM payment
GROUP BY DATE_PART('month', payment_date)
ORDER BY DATE_PART('month', payment_date);
Still learning SQL forgive me.
I have 3 tables. a material table, a material_req table and a material_trans table. I want to group by material and then group columns by year.
so it would be [material, 2019, 2018, 2017, 2016, total (total being the total qty used for each material.
I have tried to place the date in the select statement, and grouped by the date also. but then the returned result is a lot of the same material with a lot of dates. I only need the year. maybe try the same and return just the year?
SELECT material_req.Material
-- , Material_Trans_Date
, SUM(-1 * material_trans.Quantity) AS 'TOTAL'
,Standard_Cost
FROM
Material_Req inner join Material_Trans
ON
Material_Req.Material_Req = Material_Trans.Material_Req
LEFt JOIN Material
ON
Material.Material = Material_Req.Material
WHERE
material_trans.Material_Trans_Date between '20180101' AND GETDATE()
-- Material_Trans_Date between '20180101' AND '20181231'
-- Material_Trans_Date between '20170101' AND '20171231'
-- Material_Trans_Date between '20160101' AND '20161231'
GROUP BY
material_req.Material ,Standard_Cost
ORDER BY
Material_Req.Material, Standard_Cost
expected results should by grouped by material, 2019, 2018, 2017,2016, Standard_Cost. the years column will have the sum of qty for each material for that year.
results look like this current_results
If you are using SQL Server then you might try this:
SELECT material_req.Material
, SUM(CASE WHEN DATEPART(YEAR, Material_Trans_Date) = '2019' THEN material_trans.Quantity ELSE 0 END) [2019 TOTAL]
, SUM(CASE WHEN DATEPART(YEAR, Material_Trans_Date) = '2018' THEN material_trans.Quantity ELSE 0 END) [2018 TOTAL]
,Standard_Cost
FROM
Material_Req inner join Material_Trans
ON
Material_Req.Material_Req = Material_Trans.Material_Req
LEFt JOIN Material
ON
Material.Material = Material_Req.Material
WHERE
material_trans.Material_Trans_Date between '20180101' AND GETDATE()
GROUP BY
material_req.Material ,Standard_Cost
ORDER BY
Material_Req.Material, Standard_Cost
I have a requirement where I supposed to roll customer data in the prior period of 365 days.
Table:
CREATE TABLE orders (
persistent_key_str character varying,
ord_id character varying(50),
ord_submitted_date date,
item_sku_id character varying(50),
item_extended_actual_price_amt numeric(18,2)
);
Sample data:
INSERT INTO orders VALUES
('01120736182','ORD6266073' ,'2010-12-08','100856-01',39.90),
('01120736182','ORD33997609' ,'2011-11-23','100265-01',49.99),
('01120736182','ORD33997609' ,'2011-11-23','200020-01',29.99),
('01120736182','ORD33997609' ,'2011-11-23','100817-01',44.99),
('01120736182','ORD89267964' ,'2012-12-05','200251-01',79.99),
('01120736182','ORD89267964' ,'2012-12-05','200269-01',59.99),
('01011679971','ORD89332495' ,'2012-12-05','200102-01',169.99),
('01120736182','ORD89267964' ,'2012-12-05','100907-01',89.99),
('01120736182','ORD89267964' ,'2012-12-05','200840-01',129.99),
('01120736182','ORD125155068','2013-07-27','201443-01',199.99),
('01120736182','ORD167230815','2014-06-05','200141-01',59.99),
('01011679971','ORD174927624','2014-08-16','201395-01',89.99),
('01000217334','ORD92524479' ,'2012-12-20','200021-01',29.99),
('01000217334','ORD95698491' ,'2013-01-08','200021-01',19.99),
('01000217334','ORD90683621' ,'2012-12-12','200021-01',29.990),
('01000217334','ORD92524479' ,'2012-12-20','200560-01',29.99),
('01000217334','ORD145035525','2013-12-09','200972-01',49.99),
('01000217334','ORD145035525','2013-12-09','100436-01',39.99),
('01000217334','ORD90683374' ,'2012-12-12','200284-01',39.99),
('01000217334','ORD139437285','2013-11-07','201794-01',134.99),
('01000827006','W02238550001','2010-06-11','HL 101077',349.000),
('01000827006','W01738200001','2009-12-10','EL 100310 BLK',119.96),
('01000954259','P00444170001','2009-12-03','PC 100455 BRN',389.99),
('01002319116','W02242430001','2010-06-12','TR 100966',35.99),
('01002319116','W02242430002','2010-06-12','EL 100985',99.99),
('01002319116','P00532470001','2010-05-04','HO 100482',49.99);
Using the query below I am trying to get the number of distinct customers by order_submitted_date:
select
g.order_date as "Ordered",
count(distinct o.persistent_key_str) as "customers"
from
generate_series(
(select min(ord_submitted_date) from orders),
(select max(ord_submitted_date) from orders),
'1 day'
) g (order_date)
left join
orders o on o.ord_submitted_date between g.order_date - interval '364 days'
and g.order_date
WHERE extract(year from ord_submitted_date) <= 2009
group by 1
order by 1
This is the output I expected.
Ordered Customers
2009-12-03 1
2009-12-10 1
When I execute the query above I get incorrect results.
How can I make this right?
To get your expected output ("the number of distinct customers") - only days with actual orders 2009:
SELECT ord_submitted_date, count(DISTINCT persistent_key_str) AS customers
FROM orders
WHERE ord_submitted_date >= '2009-1-1'
AND ord_submitted_date < '2010-1-1'
GROUP BY 1
ORDER BY 1;
Formulate the WHERE conditions this way to make the query sargable, and input easy.
If you want one row per day (from the earliest entry up to the latest in orders) - within 2009:
SELECT ord_submitted_date AS ordered
, count(DISTINCT o.persistent_key_str) AS customers
FROM (SELECT generate_series(min(ord_submitted_date) -- single query ...
, max(ord_submitted_date) -- ... to get min / max
, '1d')::date FROM orders) g (ord_submitted_date)
LEFT join orders o USING (ord_submitted_date)
WHERE ord_submitted_date >= '2009-1-1'
AND ord_submitted_date < '2010-1-1'
GROUP BY 1
ORDER BY 1;
SQL Fiddle.
Distinct customers per year
SELECT extract(year from ord_submitted_date) AS year
, count(DISTINCT persistent_key_str) AS customers
FROM orders
GROUP BY 1
ORDER BY 1;
SQL Fiddle.
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