How to only sum unique values in postgres? - sql

I have a table below where I am trying to sum the order_value grouping by the unique order number. However, the queries I've tried are returning the entire sum. Expected return is: 34.24 but actual return is 50.37. How do I get the correct return value?
Order_Number
Order_Value
id
#1005
16.03
1
#1005
16.03
2
#1006
18.21
3
My query:
SELECT order_number,
SUM(order_value)
FROM customer_response
GROUP BY order_number ;
I've also tried:
SELECT SUM(order_value)
FROM customer_response
GROUP BY order_number, order_value
SELECT SUM(order_value)
FROM customer_response
GROUP BY order_number
This seems like it should be simple but I'm just not sure where I'm going wrong.

Very similar to your query but first extract only distinct rows for order_number.
SELECT order_number, SUM(order_value)
FROM
(
select distinct on (order_number) *
from customer_response
) t
GROUP BY order_number;
If you need to get the overall sum for all orders then remove the grouping.
SELECT SUM(order_value)
FROM
(
select distinct on (order_number) *
from customer_response
) t;
SQL Fiddle
Edit
Actually since only one row is left per order_number summing and grouping is meaningless. So the first query becomes simply
select distinct on (order_number) *
from customer_response;

You can try this :
SELECT sum(t.order_avg)
FROM
( SELECT avg(order_value) AS order_avg
FROM customer_response
GROUP BY order_number
) AS t

If you want to get the sum of all distinct Order_Values per Order_Number, you can group by Order_Number to get the sum in each group and then use SUM() window function to get the total:
SELECT DISTINCT SUM(SUM(DISTINCT Order_Value)) OVER () total_value
FROM customer_response t
GROUP BY Order_Number;
See the demo.

Related

How to select all columns with sum function

Assuming there is a table with 100 columns, how can I select all columns with a sum without having to type out all the columns?
For example something like this:
select *, sum(price) as sales
from table
group by *
order by date
try this
select table.* , t.sales from table
inner join (select id, sum(price) as sales from table group by id ) t
on table.id=t.id
order by date
But in general it is not recommended to use an stare in a select statement,
for example dont use * in table-valued function

best way to get count and distinct count of rows in single query

What is the best way to get count of rows and distinct rows in a single query?
To get distinct count we can use subquery like this:
select count(*) from
(
select distinct * from table
)
I have 15+ columns and have many duplicates rows as well and I want to calculate count of rows as well as distinct count of rows in one query.
More if I use this
select count(*) as Rowcount , count(distinct *) as DistinctCount from table
This will not give accurate results as count(distinct *) doesn't work.
Why don't you just put the subquery inside another query?
select count(*),
(select count(*) from (select distinct * from table))
from table;
create table tbl
(
col int
);
insert into tbl values(1),(2),(1),(3);
select count(*) as distinct_count, sum(sum) as all_count
from (
select count(col) sum from tbl group by col
)A
I think I have understood what you are looking for. You need to use some window function. So, you query should be look like =>
Select COUNT(*) OVER() YourRowcount ,
COUNT(*) OVER(Partition BY YourColumnofGroup) YourDistinctCount --Basic of the distinct count
FROM Yourtable
NEW Update
select top 1
COUNT(*) OVER() YourRowcount,
DENSE_RANK() OVER(ORDER BY YourColumn) YourDistinctCount
FROM Yourtable ORDER BY TT DESC
Note: This code is written sql server. Please check the code and let me know.

SQL Total Distinct Count on Group By Query

Trying to get an overall distinct count of the employees for a range of records which has a group by on it.
I've tried using the "over()" clause but couldn't get that to work. Best to explain using an example so please see my script below and wanted result below.
EDIT:
I should mention I'm hoping for a solution that does not use a sub-query based on my "sales_detail" table below because in my real example, the "sales_detail" table is a very complex sub-query.
Here's the result I want. Column "wanted_result" should be 9:
Sample script:
CREATE TEMPORARY TABLE [sales_detail] (
[employee] varchar(100),[customer] varchar(100),[startdate] varchar(100),[enddate] varchar(100),[saleday] int,[timeframe] varchar(100),[saleqty] numeric(18,4)
);
INSERT INTO [sales_detail]
([employee],[customer],[startdate],[enddate],[saleday],[timeframe],[saleqty])
VALUES
('Wendy','Chris','8/1/2019','8/12/2019','5','Afternoon','1'),
('Wendy','Chris','8/1/2019','8/12/2019','5','Morning','5'),
('Wendy','Chris','8/1/2019','8/12/2019','6','Morning','6'),
('Dexter','Chris','8/1/2019','8/12/2019','2','Mid','2.5'),
('Jennifer','Chris','8/1/2019','8/12/2019','4','Morning','2.75'),
('Lila','Chris','8/1/2019','8/12/2019','2','Morning','3.75'),
('Rita','Chris','8/1/2019','8/12/2019','2','Mid','1'),
('Tony','Chris','8/1/2019','8/12/2019','4','Mid','2'),
('Tony','Chris','8/1/2019','8/12/2019','1','Morning','6'),
('Mike','Chris','8/1/2019','8/12/2019','4','Mid','1.5'),
('Logan','Chris','8/1/2019','8/12/2019','3','Morning','6.25'),
('Blake','Chris','8/1/2019','8/12/2019','4','Afternoon','0.5')
;
SELECT
[timeframe],
SUM([saleqty]) AS [total_qty],
COUNT(DISTINCT [s].[employee]) AS [employee_count1],
SUM(COUNT(DISTINCT [s].[employee])) OVER() AS [employee_count2],
9 AS [wanted_result]
FROM (
SELECT
[employee],[customer],[startdate],[enddate],[saleday],[timeframe],[saleqty]
FROM
[sales_detail]
) AS [s]
GROUP BY
[timeframe]
;
If I understand correctly, you are simply looking for a COUNT(DISTINCT) for all employees in the table? I believe this query will return the results you are looking for:
SELECT
[timeframe],
SUM([saleqty]) AS [total_qty],
COUNT(DISTINCT [s].[employee]) AS [employee_count1],
(SELECT COUNT(DISTINCT [employee]) FROM [sales_detail]) AS [employee_count2],
9 AS [wanted_result]
FROM #sales_detail [s]
GROUP BY
[timeframe]
You can try this below option-
SELECT
[timeframe],
SUM([saleqty]) AS [total_qty],
COUNT(DISTINCT [s].[employee]) AS [employee_count1],
SUM(COUNT(DISTINCT [s].[employee])) OVER() AS [employee_count2],
[wanted_result]
-- select count form sub query
FROM (
SELECT
[employee],[customer],[startdate],[enddate],[saleday],[timeframe],[saleqty],
(select COUNT(DISTINCT [employee]) from [sales_detail]) AS [wanted_result]
--caculate the count with first sub query
FROM [sales_detail]
) AS [s]
GROUP BY
[timeframe],[wanted_result]
Use a trick where you only count each person on the first day they are seen:
select timeframe, sum(saleqty) as total_qty),
count(distinct employee) as employee_count1,
sum( (seqnum = 1)::int ) as employee_count2
9 as wanted_result
from (select sd.*,
row_number() over (partition by employee order by startdate) as seqnum
from sales_detail sd
) sd
group by timeframe;
Note: From the perspective of performance, your complex subquery is only evaluated once.

How to SUM multiple distinct values and get max value in SQL

I'm a using distinct select in the Oracle SQL, what I want to do is sum up all the data at specific ID. Example in image:
So for example where PlayerIDFK is 1 I want to sum up TwoPointsMade in one column and ThrePointsMade in another, so for that the result would be
PlayerIDFK TwoPointsMade ThreePointsMade
--------------------------------------------------
1 5 2
The query Im using now is:
SELECT PlayerIDFK, TwoPointMade, ThreePointMade
FROM PlayerPerformance
WHERE PlayerIDFK IN (SELECT DISTINCT PlayerIDFK
FROM PlayerPerformance);
I think you could use the groupby-clause where you could group by playerIDFK and sum over twopointsmade and threepointsmade
Something like this might work:
SELECT PlayerIDFK, sum(TwoPointMade), sum(ThreePointMade) FROM PlayerPerformance GROUP BY PlayerIDFK
if you want to get the max you can do a nested query, something like this:
SELECT MAX(inside_query.m1, inside_query.m2) FROM (SELECT PlayerIDFK, sum(TwoPointMade) as m1, sum(ThreePointMade)as m2 FROM PlayerPerformance GROUP BY PlayerIDFK) as inside_query
there might be a more elegant way to do it but thats what I got :)
Maybe this might help:
SELECT * FROM (
SELECT PlayerIDFK, sum(TwoPointMade) as TwoPointMade
FROM PlayerPerformance
GROUP BY PlayerIDFK
ORDER BY sum(TwoPointMade) DESC
) WHERE ROWNUM = 1
UNION ALL
SELECT * FROM (
SELECT PlayerIDFK, sum(ThreePointMade) as ThreePointMade
FROM PlayerPerformance
GROUP BY PlayerIDFK
ORDER BY sum(ThreePointMade) DESC
) WHERE ROWNUM = 1

How to put the Order BY in SQL UNION so TOTALS will show up always as last row?

I have SQL UNION where second part of that statement is the row that represents TOTALS. How can I ORDER BY where TOTALS will ALWAYS will show up as the last row?
Add an extra column to the queries being UNIONed, and make that column the first column in your ORDER BY clause.
So if I started with something like this:
SELECT product, price
FROM table
UNION
SELECT 'Total' AS product, SUM(price)
FROM table
I'd add a new column like this:
SELECT product, price
FROM (
SELECT product, price, 0 AS union_order
FROM table
UNION
SELECT 'Total' AS product, SUM(price), 1 AS union_order
FROM table
)
ORDER BY union_order
That way, regular products appear first, then the total appears at the end.
Have you tried using GROUP BY ROLLUP - it might be just want you want, although it's difficult to tell when you haven't posted your query.
You could try adding an 'order' column to each query and then order by that column...
SELECT x.*
FROM
(
SELECT columns, 2 AS [Order]
UNION
SELECT totals, 1 AS [Order]
) x
ORDER BY x.[Order]
select * from
(
select 1 as prio
, col1
, col2
...
from tableA
union
select 2 as prio
, totalCol1
, totalCol2
...
from tableB
) order by prio