This question has probably been asked in different formats, but I could not find the answer.
I have table orders
date, quantity_ordered, unit_cost_cents , product_model_number, title
I would like to:
SELECT
model_number,
title,
SUM(unit_cost_cents / 100.00 * quantity_ordered) as total
FROM orders
GROUP BY model_number
HAVING SUM(quantity_submitted) > 0
ORDER BY total DESC
But it requires grouping by the title as well.
My problem being is that my title changes over time. I'd like to preserve the titles and simply display/select the most recent title without grouping by title which would make the numbers different.
You can use a subquery to fetch the latest title:
SELECT
model_number,
(select max(title) from orders where date = (
select max(date) from orders where model_number = o.model_number)
) title,
SUM(unit_cost_cents / 100.00 * quantity_ordered) as total
FROM orders o
GROUP BY model_number
HAVING SUM(quantity_submitted) > 0
ORDER BY total DESC
I used select max(title) instead of select title to make sure that the subquery will not return more than 1 rows (just in case).
SELECT
o.model_number
, om.title
, SUM(o.unit_cost_cents / 100.00 * o.quantity_ordered) as total
FROM orders o
JOIN (SELECT model_number, title
,row_number() OVER (PARTITION BY model_number ORDER BY zdate DESC) AS rn
FROM orders) om
ON om.model_number=o.model_number AND om.rn=1
GROUP BY 1,2
HAVING SUM(o.quantity_submitted) > 0
ORDER BY 3 DESC
;
Related
Im trying to find the distributor with the highest and lowest quantity for each country
in two columns distributor with minimum quantity and maximum quantity
I have been able to get the information from other posts but it is in a column however I want it on a row per country
See http://sqlfiddle.com/#!17/448f6/2
Desired result
"country" "min_qty_name" "max_qty_name"
1. "Madagascar" "Leonard Cardenas" "Gwendolyn Mccarty"
2. "Malaysia" "Arsenio Knowles" "Yael Carter"
3. "Palau" "Brittany Burris" "Clark Weaver"
4. "Tanzania" "Levi Douglas" "Levi Douglas"
You can use subqueries:
select distinct country,
(select distributor_name
from product
where country = p.country
order by quantity limit 1) as min_qty_name,
(select distributor_name
from product
where country = p.country
order by quantity desc limit 1) as max_qty_name
from product p;
Fiddle
You can do it with cte too (result here)
WITH max_table AS
(
SELECT ROW_NUMBER() OVER (partition by country order by country,quantity DESC) AS rank,
country, quantity,distributor_name
FROM
product
),
min_table AS
(
SELECT ROW_NUMBER() OVER (partition by country order by country,quantity) AS rank,
country, quantity,distributor_name
FROM
product
)
SELECT m1.country,m2.distributor_name,m1.distributor_name
from max_table m1, min_table m2
where m1.country = m2.country
and m1.rank = 1 and m2.rank = 1
You can do this with a single sort and pass through the data as follows:
with min_max as (
select distinct country,
first_value(distributor_name) over w as min_qty_name,
last_value(distributor_name) over w as max_qty_name
from product
window w as (partition by country
order by quantity
rows between unbounded preceding
and unbounded following)
)
select *
from min_max
order by min_max;
Updated Fiddle
SELECT partner_id
FROM trip_delivery_sales ts
WHERE ts.route_id='152'
GROUP BY ts.partner_id
From the query we can get the partners id.Using that partner id we want check in trip delicery sales lines table and want to find each customer last two sale product quantity sum. If last two sale have product qty as 2 & 5 want result as partner_id | count as Mn2333 - 7
here fore example i take partner id as 34806. But i want to check all partner_id obtained from last query
SELECT product_qty
FROM trip_delivery_sales_lines td
WHERE td.partner_id='34806'
AND td.route_id='152'
AND td.product_id='432'
ORDER BY td.order_date DESC
LIMIT 2
You can run this query
SELECT td.partner_id,sum(product_qty)
FROM trip_delivery_sales_lines td,
(SELECT partner_id FROM trip_delivery_sales ts WHERE ts.route_id='152') as ts
WHERE td.partner_id=ts.partner_id
AND td.product_id='432'
GROUP BY td.partner_id
ORDER BY td.order_date DESC
LIMIT 2
Or this one
with ts as (SELECT distinct partner_id FROM trip_delivery_sales WHERE route_id='152')
SELECT td.partner_id,sum(product_qty)
FROM trip_delivery_sales_lines td,ts
WHERE td.partner_id=ts.partner_id
AND td.product_id='432'
GROUP BY td.partner_id
ORDER BY td.order_date DESC
LIMIT 2
You might be looking for
SELECT DISTINCT ts.partner_id, ARRAY(
SELECT product_qty
FROM trip_delivery_sales_lines td
WHERE td.partner_id=ts.partner_id
AND td.product_id='432'
ORDER BY td.order_date DESC
LIMIT 2
) AS product_qty_arr
FROM trip_delivery_sales ts
WHERE ts.route_id='152'
or just
SELECT
partner_id,
array_agg(product_qty ORDER BY order_date DESC) as product_qty_arr
FROM (
SELECT
td.partner_id,
td.product_qty,
td.order_date,
row_number() OVER (PARTITION BY td.partner_id ORDER BY td.order_date DESC)
FROM trip_delivery_sales_lines td
JOIN trip_delivery_sales ts USING (partner_id)
WHERE ts.route_id='152'
AND td.product_id='432'
) AS enumerated
WHERE row_number <= 2
GROUP BY partner_id
See also PostgreSQL: top n entries per item in same table or Optimize GROUP BY query to retrieve latest row per user
In POSTGRESQL 13, I have a table of ids,dates, prices.
I simply want to have the latest date where the price is greater than 0 per id.
One row per id.
So the optimal output is :
id | the_date | price
1 2013-08-09 0.45
2 2013-08-11 0.34
I have an SQL fiddle at this link :
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=a89bbbc922601be5465ad764fd035161
I have tried an INNER JOIN with the MAX date unsuccessfully.
SELECT DISTINCT ON (id)
id, the_date, price
FROM inventory
WHERE price>0
ORDER BY id ASC, the_date DESC
You can do something like this:
select i.id, i.the_date, i.price
from inventory as i, (
select id, max(the_date) as max_date
from inventory
where price > 0
group by id
) as c where c.id = i.id and i.the_date = c.max_date
Demo in dbfiddle.uk
This might work for you.
SELECT inventory.id, the_date, price
FROM inventory
join (select id,max(the_date) md from inventory where price>0 group by id ) d
on inventory.id=d.id and the_date=d.md
If you want a row for id's with not price you'd use left join.
Let's say I have an orders table with customer_id, order_total, and order_date columns. I'd like to build a report that shows all customers who haven't placed an order in the last 30 days, with a column for the total amount their last order was.
This gets all of the customers who should be on the report:
select customer, max(order_date), (select order_total from orders o2 where o2.customer = orders.customer order by order_date desc limit 1)
from orders
group by 1
having max(order_date) < NOW() - '30 days'::interval
Is there a better way to do this that doesn't require a subquery but instead uses a window function or other more efficient method in order to access the total amount from the most recent order? The techniques from How to select id with max date group by category in PostgreSQL? are related, but the extra having restriction seems to stop me from using something like DISTINCT ON.
demo:db<>fiddle
Solution with row_number window function (https://www.postgresql.org/docs/current/static/tutorial-window.html)
SELECT
customer, order_date, order_total
FROM (
SELECT
*,
first_value(order_date) OVER w as last_order,
first_value(order_total) OVER w as last_total,
row_number() OVER w as row_count
FROM orders
WINDOW w AS (PARTITION BY customer ORDER BY order_date DESC)
) s
WHERE row_count = 1 AND order_date < CURRENT_DATE - 30
Solution with DISTINCT ON (https://www.postgresql.org/docs/9.5/static/sql-select.html#SQL-DISTINCT):
SELECT
customer, order_date, order_total
FROM (
SELECT DISTINCT ON (customer)
*,
first_value(order_date) OVER w as last_order,
first_value(order_total) OVER w as last_total
FROM orders
WINDOW w AS (PARTITION BY customer ORDER BY order_date DESC)
ORDER BY customer, order_date DESC
) s
WHERE order_date < CURRENT_DATE - 30
Explanation:
In both solutions I am working with the first_value window function. The window function's frame is defined by customers. The rows within the customers' groups are ordered descending by date which gives the latest row first (last_value is not working as expected every time). So it is possible to get the last order_date and the last order_total of this order.
The difference between both solutions is the filtering. I showed both versions because sometimes one of them is significantly faster
The window function style is creating a row count within the frames. Every first row can be filtered later. This is done by adding a row_number window function. The benefit of this solution comes out when you are trying to filter the first two or three data sets. You simply have to change the filter from WHERE row_count = 1 to WHERE row_count = 2
But if you want only one single row per group you just need to ensure that the expected row per group is ordered to be the first row in the group. Then the DISTINCT ON function can delete all following rows. DISTINCT ON (customer) gives the first (ordered) row per customer group.
Try to join table on itself
select o1.customer, max(order_date),
from orders o1
join orders o2 on o1.id=o2.id
group by o1.customer
having max(o1.order_date) < NOW() - '30 days'::interval
Subqueries in select is a bad idea, because DB will execute a query for each row
If you use postgres you can also try to use CTE
https://www.postgresql.org/docs/9.6/static/queries-with.html
WITH t as (
select id, order_total from orders o2 where o2.customer = orders.customer
order by order_date desc limit 1
) select o1.customer, max(order_date),
from orders o1
join t t.id=o2.id
group by o1.customer
having max(order_date) < NOW() - '30 days'::interval
I have a query. this query is calculated percentage for every product. I created a virtual column on this query this columns name is 'yüzde'. After that, i want to transfer yüzde columns to another column in another table with update query if product ids are same.
I think I need to write a stored procedure. How can I do that?
SELECT [ProductVariantId] ,
count([ProductVariantId]) as bedensayısı,
count([ProductVariantId]) * 100.0 / (SELECT Top 1 Count(*) as Total
FROM [Live_ADL].[dbo].[_INV_ProductCombinationAttributes]
Where Size LIKE '%[^0-9]%' and [StockQuantity]>0
Group by [ProductVariantId]
order by Total Desc) as yüzde
FROM [Live_ADL].[dbo].[_INV_ProductCombinationAttributes]
Where Size LIKE '%[^0-9]%' and [StockQuantity]>0
group by [ProductVariantId]
order by yüzde desc
you don't really need a SP, you can do it in-line, using CTE for instance, something along these lines:
; with tabyuzde as
(
SELECT [ProductVariantId] ,
count([ProductVariantId]) as bedensayısı,
count([ProductVariantId]) * 100.0 / (SELECT Top 1 Count(*) as Total
FROM [Live_ADL].[dbo].[_INV_ProductCombinationAttributes]
Where Size LIKE '%[^0-9]%' and [StockQuantity]>0
Group by [ProductVariantId]
order by Total Desc) as yüzde
FROM [Live_ADL].[dbo].[_INV_ProductCombinationAttributes]
Where Size LIKE '%[^0-9]%' and [StockQuantity]>0
group by [ProductVariantId]
)
update x
set othertablevalue=yüzde
from
othertable x
join tabyuzde t on x.ProductVariantId=t.ProductVariantId