A table and I want to know the total of my rows over time. For example. Here's my table:
Date Fruit Sold
Mon apple 4
Mon pear 5
Mon orange 2
Tues apple 3
Tues pear 2
Tues orange 1
The table I want back is:
Fruit Sold
apple 7
pear 7
orange 3
What is a query that I can do this? However, with my real situation, I have hundreds of types of fruit. So how do I query with out specifying each type of fruit each time?
That would be along the lines of:
select fruit, sum(sold) as sold
from fruitsales
group by fruit
-- adding something like <<where date = 'Mon'>> if you want to limit it.
This will aggregate the individual sold columns (by summing) for each fruit type.
here is how to do it:
select fruit, sum(sold)
from table
group by fruit
cheers...
Group by Time
select fruit, sum(sold),substring(saletime,1,3) from table group by fruit,substring(saletime,1,3)
Related
Not sure how to explain this..
I have a similar table, but i have simplified it with the following:
I have a table of goods shipped to different cusotmers. Some have bought apples only, others have bought apples and potates.
I want an SQL query to return only customers where "To be billed" = Yes AND the customer hasnt bought any vegetables.
So for example if the table looks like this:
Item
Name
Group
To_be_billed
CustomerNo.
2000
Apple
Fruit
Yes
1
2000
Apple
Fruit
No
2
2000
Apple
Fruit
No
3
2000
Apple
Fruit
Yes
4
2000
Apple
Fruit
Yes
5
4000
Potato
Vegetable
No
2
4000
Potato
Vegetable
No
4
I want the query to return:
Item
Name
Group
To_be_billed
CustomerNo.
2000
Apple
Fruit
Yes
1
2000
Apple
Fruit
Yes
5
The reason 4 has bought apples, and is to be billed, but the customer also bought Potatoes, so is to be ignored...
You can create a CTE to check for CustomerNo.s that you need to ignore, and then use not exists:
with bought_veg as
(
select "CustomerNo."
from tbl
where tbl."Group" like 'Vegetable'
)
select tbl.*
from tbl
where not exists (select 1 from bought_veg where tbl."CustomerNo." = bought_veg."CustomerNo.")
and tbl.To_be_billed = 'Yes'
Example without CTE:
select tbl.*
from tbl
where not exists (select "CustomerNo." from tbl t2 where tbl.[CustomerNo.] = t2.[CustomerNo.] and "Group" like 'Vegetable')
and tbl.To_be_billed = 'Yes'
Hi I have a table that shows the category of product and another table with daily price of the product. I would like to get the average price of the category where average not count null values. How do I achieve this? Example of table product
product
category
apple
fruit
pear
fruit
grape
fruit
celery
vegetables
cabbage
vegetables
chicken
meat
turkey
meat
beef
meat
another table with daily price and productid as columns and the price in the rows
date
apple
pear
grape
celery
cabbage
chicken
turkey
beef
2022-01-01
2
4
1
2
3
4
3
2022-01-02
2
2
2
4
3
2022-01-03
2
2
2
3
into
date
fruit
vegetables
meat
2022-01-01
3
1.5
3.3
2022-01-02
2
2
3.5
2022-01-02
2
2
3
Where average is only to columns where it is not null, it would be better not to do it manually.
Consider below query using UNPIVOT AND PIVOT:
SELECT * FROM (
SELECT date, category, price
FROM prices UNPIVOT (price FOR productid IN (apple, pear, grape, celery, cabbage, chicken, turkey, beef)) p
JOIN category c ON c.product = p.productid
) PIVOT (AVG(price) FOR category IN ('fruit', 'vegetables', 'meat'))
ORDER BY date;
Consider also below approach
create temp function keys(input string) returns array<string> language js as """
return Object.keys(JSON.parse(input));
""";
create temp function values(input string) returns array<string> language js as """
return Object.values(JSON.parse(input));
""";
select *
from (
select date, category, round(avg(safe_cast(price as float64)), 2) avg_price
from prices t, unnest([struct(to_json_string(t) as json)]),
unnest(keys(json)) product with offset
join unnest(values(json)) price with offset using(offset)
left join products using(product)
where product != 'date'
group by date, category
)
pivot (any_value(avg_price) for category IN ('fruit', 'vegetables', 'meat'))
if applied to sample data in your question - output is
Potential benefit of using above is to eliminate need in enlisting all column names from products table, which are 8 in your example but in reality most likely much more! Obviously, another way to address this is to build dynamic query and run it using execute immediate which you can find quite a number of examples here on SO.
But, assuming that number of categories is significantly lower (just few as in your example) to compare with number of products - I would use this approach as execute immediate has its own drawbacks ...
Hi I have data similar to for table : fruit_table
Product Code
Product
Date
MG
Mango
2020-01-25
MG
Mango
2020-01-26
MG
Mango
2020-01-27
MG
Mango
2020-01-28
BN
Banana
2019-01-15
BN
Banana
2020-01-19
BN
Banana
2020-01-20
BN
Banana
2016-01-20
AP
APPLE
2021-03-02
As you can see in the data we have Mango 4 products and Banana 4 Products and Apple with 1 product, i want the solution is to limit the products with 2 rows with latest date.
And i want output similar to
Product Code
Product
Date
MG
Mango
2020-01-27
MG
Mango
2020-01-28
BN
Banana
2020-01-19
BN
Banana
2020-01-20
AP
APPLE
2021-03-02
How can this be achieved with a simple query in PostgreSQL query.
Thanks in advance.
demo:db<>fiddle
You can use row_number() window function to achieve that:
SELECT
*
FROM (
SELECT
*,
row_number() OVER (PARTITION BY "Product Code" ORDER BY "Date" DESC) -- 1
FROM fruit_table
) s
WHERE row_number <= 2 -- 2
row_number() adds a row count to each record in an ordered group (= partition). In your case the group is the Product Code (or Product) and you need to order each group by Date DESC to get the most recent dates to the top. Now the most recent date in each group gets the row count 1, the second recent one the 2 and so on
Using this row count you can filter only the two top records of each group.
As a note: If you have a separate table of products, then you might find that a lateral join is faster:
select ft.*
from products cross join lateral
(select ft.*
from fruit_table ft
where ft.product = p.product
order by ft.date desc
limit 2
) ft;
Like the solution using row_number() this will take advantage of an index on fruit_table(product, date). However, I think the performance would usually be a little better (basically because it does not assign row number values to all rows before filtering them out).
I have records similar to the below
fruit day
apple 1/1/1990
apple 1/2/1990
apple 1/3/1990
plum 1/1/1990
orange 1/1/1990
orange 1/2/1990
orange 1/3/1990
I want to keep a running total for items for each day assuming item will increase by 1 every day. For example
fruit day count
apple 1/1/1990 1
apple 1/2/1990 2
apple 1/3/1990 3
plum 1/1/1990 1
orange 1/1/1990 1
orange 1/2/1990 2
You could use windowed COUNT:
SELECT *, COUNT(*) OVER(PARTITION BY fruit ORDER BY day)
FROM tab;
DBFiddle Demo
You can also use subquery:
select *,
(select count(*) from table where fruit = t.fruit and day <= t.day) count
from table t;
Say I have a table showing the type of fruit consumed by an individual over a 24 hour period that looks like this:
Name Fruit
Tim Apple
Tim Orange
Tim Orange
Tim Orange
Lisa Peach
Lisa Apple
Lisa Peach
Eric Plum
Eric Orange
Eric Plum
How would I get a table that shows only the most consumed fruit for each person, as well as the number of fruits consumed. In other words, a table that looks like this:
Name Fruit Number
Tim Orange 3
Lisa Peach 2
Eric Plum 2
I tried
SELECT Name, Fruit, Count(Fruit)
FROM table
GROUP BY Name
But that returns an error because Name needs to be in the GROUP BY statement as well. Every other method I've tried returns the counts for ALL values rather than just the maximum values. MAX(COUNT()) doesn't appear to be a valid statement, so I'm not sure what else to do.
This is a pain, but you can do it. Start with your query and then use join:
SELECT n.Name, n.Fruit
FROM (SELECT Name, Fruit, Count(Fruit) as cnt
FROM table as t
GROUP BY Name, Fruit
) as t INNER JOIN
(SELECT Name, max(cnt) as maxcnt
FROM (SELECT Name, Fruit, Count(Fruit) as cnt
FROM table
GROUP BY Name, Fruit
) as t
GROUP BY Name
) as n
ON t.name = n.name and t.cnt = n.maxcnt;