Postgresql conditional sum - postgresql

I have a table with the following data for sales and inventory (oh):
category sales oh item_num
Clothes 12 10 1
Clothes 11 10 1
Clothes 10 10 1
Clothes 5 10 1
Clothes 8 10 1
Clothes 4 10 1
Clothes 23 10 2
Clothes 5 10 2
Clothes 20 10 2
Clothes 5 10 2
Clothes 13 10 2
Clothes 9 10 2
Food 6 25 3
Food 8 25 3
Food 7 25 3
Food 14 25 3
I am trying to query this table to get a sum of both the sales and oh columns by category:
SELECT category, SUM(sales) AS sales, SUM(oh) AS oh
FROM data
GROUP BY category
However, the problem is I need the SUM(oh) to only sum distinct items but the SUM(sales) to sum all the values. So the result should be:
category sales oh
Clothes 125 20
Food 35 25
I tried SUM(DISTINCT oh), but that only works for distinct oh values not distinct items. I really need something like SUM(DISTINCT(item_num) oh).
I experimented with various window functions, but could not come up with a solution. Does anyone know how to return this kind of sum on a unique key?

Here's how I'd do it:
SELECT category, SUM(sales) AS sales, SUM(oh) AS oh
FROM (
SELECT category, SUM(sales) AS sales, oh
FROM data
GROUP BY category, item_num, oh
) ttl
GROUP BY category;
Basically tackle the problem in stages. First group up the items by category and item number to get the sum of sales then group and sum by category to get the sum of oh.
Result:
category | sales | oh
----------+-------+----
Food | 35 | 25
Clothes | 125 | 20
(2 rows)
Edit: Included simplified query.

Related

Calculate Subtotals using fixed categories in postgresql query

I have a query that returns the count and sum of certain fields on my tables, and also a total. It goes like this:
example:
with foo as(
select s.subcat as subcategory,
sum(s.cost) as costs,
round(((sum(s.cost) / (s.tl)::numeric )*100),2)|| ' %' as pct_cost
from (select ...big query)s group by s.subcat
)
select * from foo
union
select 'Total costs' as subcategory,
sum(costs) as costs,
null as pct_cost
from foo
order by...
Category
Cost
Percentage
x_subcategory 1
5
0.5%
x_subcategory 2
1
0.1%
x_subcategory 3
18
1.8%
y_subcategory 1
7
0.7%
y_subcategory 2
10
1.0%
...
...
...
Total
41
5.8%
And what I need to do for another report is to get the totals by Category. I have to assign these categories based on the value of the subcategory name, the point is how to partition the result so I can get something like this:
Category
Cost
Percentage
x_subcategory 1
5
0.5%
x_subcategory 2
1
0.1%
x_subcategory 3
18
1.8%
X category
24
2.4%
y_subcategory 1
7
0.7%
y_subcategory 2
10
1.0%
Y category
17
1.7%
With GROUP BY and GROUP BY GROUPING SET I don't get what I want, and with PARTITION I'm getting syntax errors, I'm able to use it in simpler queries but this one turned out to be very complicated and I wonder if it's possible to achieve this on a query on PostgreSQL.

Full Outer Joins In PostgreSql [duplicate]

This question already has answers here:
Left Outer Join Not Working?
(4 answers)
Closed 4 years ago.
I've created a table of students with columns student_id as primary key,
student_name and gender.
I've an another table gender which consists of gender_id and gender.
gender_id in student refers to table gender.
Tables data looks like this:
Student table
STUDENT_ID STUDENT_NAME GENDER
1 Ajith 1
2 Alan 1
3 Ann 2
4 Alexa 2
5 Amith 1
6 Nisha 2
7 Rathan 1
8 Rebecca 2
9 asdf null
10 asd null
11 dbss null
Gender Table
GENDER_ID GENDER
1 Male
2 Female
3 Others
My query and its result
SELECT S.STUDENT_NAME,
G.GENDER
FROM STUDENTS S
FULL OUTER JOIN GENDER G ON G.GENDER_ID = S.GENDER
result is giving with 12 rows including the Others value from the gender table.
STUDENT_ID STUDENT_NAME GENDER
1 Ajith Male
2 Alan Male
3 Ann Female
4 Alexa Female
5 Amith Male
6 Nisha Female
7 Rathan Male
8 Rebecca Female
Others
9 asdf
10 asd
11 dbss
I'm trying to restrict a particular student_id:
SELECT S.STUDENT_ID,
S.STUDENT_NAME,
G.GENDER
FROM STUDENTS S
FULL OUTER JOIN GENDER G ON G.GENDER_ID = S.GENDER
WHERE S.STUDENT_ID <> 11;
now the the total number of the rows are reduced to 10.
STUDENT_ID STUDENT_NAME GENDER
1 Ajith Male
2 Alan Male
3 Ann Female
4 Alexa Female
5 Amith Male
6 Nisha Female
7 Rathan Male
8 Rebecca Female
9 asdf
10 asd
Why has the one row with Others Values disappeared from the second select query?
I'm trying to find the cause of this issue.
That's because NULL <> 11 is not TRUE, but NULL, and only rows where the condition is TRUE are included in the result.
You'd have to write something like
WHERE s.student_id IS DISTINCT FROM 11
Your second select query returns all rows where student_id is different (<>) from 11.

duplicating table columns in KDB

Consider the code below:
q)tab:flip `items`sales`prices!(`nut`bolt`cam`cog;6 8 0 3;10 20 15 20)
q)tab
items sales prices
------------------
nut 6 10
bolt 8 20
cam 0 15
cog 3 20
I would like to duplicate the prices column. I can write a query like this:
q)update prices_copy: prices from tab
I also can write a query like this:
q)select items, sales, prices, prices_copy: first prices by items from tab
Both would work. I would like to know how the "by" version would work and the motivation for writing each version. I cannot help but think the "by" version is more thinking in rows.
Your initial query would be ideally what you want for your duplicate column requirement.
The by creates groups of the column items in your example and collapses every other column in the select query according to the indices calculated from grouping items. More info on by here - http://code.kx.com/wiki/Reference/select and http://code.kx.com/wiki/JB:QforMortals2/queries_q_sql#The_by_Phrase
In your example, the column items is already unique and so no collapsing into groups is actually performed, however, the by will create nested lists from the other columns (i.e. lists of lists). The use of first will just un-nest the items column, thus collapsing it to a normal (long-typed) vector.
When the grouping is finished the by columns are used as the key column[s] of the result and you will see this by the use of a vertical line to the right hand side of the key column[s]. All other columns within the select query are placed to the right hand side of the key.
The logic of the by version coincidentally creates a copy of prices. But by changes the order:
q)ungroup select sales, prices by items from tab
items sales prices
------------------
bolt 8 20
cam 0 15
cog 3 20
nut 6 10
q)tab
items sales prices
------------------
nut 6 10
bolt 8 20
cam 0 15
cog 3 20
The by version works only because items is unique. For a tab with multiple values for item eg. 8#tab, the query only produces 4 values for prices_copy.
q)select items, sales, prices, prices_copy: first prices by items from 8#tab
items| items sales prices prices_copy
-----| ----------------------------------
bolt | bolt bolt 8 8 20 20 20
cam | cam cam 0 0 15 15 15
cog | cog cog 3 3 20 20 20
nut | nut nut 6 6 10 10 10
There is a fundamental difference between a simple update and update by queries.
Let's explore it by adding an extra column brand to the table
tab2:flip `items`sales`prices`brand!(`nut`bolt`cam`cog`nut`bolt`cam`cog;6 8 0 3 1 2 3 4;10 20 15 20 30 40 50 60;`b1`b1`b1`b1`b2`b2`b2`b2)
The following will now simply copy the column :
asc update prices_copy: prices from tab2
However, the following query is copying the first item price regardless of the brand and updating it for all other brands of same item.
asc ungroup select sales, prices,brand, prices_copy: first prices by items from tab2
items sales prices brand prices_copy
------------------------------------
bolt 2 40 b2 20
bolt 8 20 b1 20 //b2 price
cam 0 15 b1 15 //b2 price
cam 3 50 b2 15
cog 3 20 b1 20
cog 4 60 b2 20 //b2 price
nut 1 30 b2 10 //b2 price
nut 6 10 b1 10
update by might be useful in the case where you want to copy the max price of the items regardless of the brand or some other aggregation query.
asc ungroup select sales, prices,brand, prices_copy: max prices by items from tab2
items sales prices brand prices_copy
------------------------------------
bolt 2 40 b2 40
bolt 8 20 b1 40 //max price in bolts regardless of the brand
cam 0 15 b1 50
cam 3 50 b2 50
cog 3 20 b1 60
cog 4 60 b2 60
nut 1 30 b2 30
nut 6 10 b1 30

Merge Results in Crystal Reports

ID THINGS QTY PRICE
123 bag 1 25
123 shoes 1 10
123 pen 1 40
123 dress 1 20
The result in my report:
I put all the fields in sub_reports under group footer
bag 25x1 25
shoes 10x1 10
pen 40x1 40
dress 20x1 20
How can I merge them resulting to:
Materials 95x4 95
Can you help me.
As Siva suggested, you should probably have a Group created using your ID field, then Insert summary fields for sum(price) and sum(quantity) at the ID group. This will insert totals for both at the group footer

How to group by one column and summation of second?

tsql newbie here.
I have a table, similar to this one:
CarId CarName UserId RentedTimes CrashedTimes
`````````````````````````````````````````````````````````
1 Ferrari 1 2 0
2 DB9 1 5 0
3 Ferrari 2 4 0
4 Audi 3 1 0
5 Audi 1 1 0
Assuming the table is called 'Cars', I am trying to select total number of times each of cars were rented. According to the table above, Ferrari was rented total of 6 times, DB9 five times and Audi twice.
I tried doing this:
select CarName, SUM(RentedTimes)
from Cars
group by CarName, RentedTimes
order by RentedTimes desc
but, it is returning two rows of ferrari with 2,4 as rented times and so on..
How do I select all cars, and total times each were rented, please?
Thanks
Edited the query to include sort order, sorry.
select CarName, SUM(RentedTimes)
from Cars
group by CarName
ORDER BY SUM(RentedTimes) DESC
Try this way.. removed RentedTimes from group by