Find the Product Number - sql

I am trying to find the product number/product name based on the following set of conditions:
Select top 1 productnumber in xyz table
where product number in (1,2,3) order by filingdate --only if the last filing date has this product number
If product number in (4,5,6) for the last filing date nothing should be selected
If product number not in (4,5,6) for the last filing, then select the next top 1 productnumber
where prodcutnumber in (1,2,3) order by filingdate
how can i achieve this in a single query, i tried case statement bu i am stuck with it.
Sample data:
pnumber fnumber fdate
1 1 12/31
2 1 12/10
1 2 12/10
4 2 12/11
5 2 12/12
7 3 12/12
1 3 12/11
the results should be
pnumber fnumber fdate
1 1 12/31
1 2 12/10
1 3 12/11

Try by giving datatype as varchar for fdate.
SELECT id,
funum,
fdate
FROM (SELECT Row_number()
OVER(
partition BY funum
ORDER BY id) rn,
*
FROM t)p
WHERE rn = 1

Related

SQL subquery with comparison

On a Rails (5.2) app with PostgreSQL I have 2 tables: Item and ItemPrice where an item has many item_prices.
Table Item
id
name
1
poetry book
2
programming book
Table ItemPrice
id
item_id
price
1
1
4
2
2
20
3
1
8
4
1
6
5
2
22
I am trying to select all the items for which the last price (price of the last offer price attached to it) is smaller than the one before it
So in this example, my request should only return item 1 because 6 < 8, and not item 2 because 22 > 20
I tried various combinations of Active records and SQL subqueries that would allow me to compare the last price with the second to last price but failed so far.
ex Item.all.joins(:item_prices).where('EXISTS(SELECT price FROM item_prices ORDER BY ID DESC LIMIT 1 as last_price WHERE (SELECT price FROM item_prices ... can't work it out..
You can do it as follows using ROW_NUMBER and LAG:
LAG to get the previous row based on a condition
WITH ranked_items AS (
SELECT m.*,
ROW_NUMBER() OVER (PARTITION BY item_id ORDER BY id DESC) AS rn,
LAG(price,1) OVER (PARTITION BY item_id ORDER BY id ) previous_price
FROM ItemPrice AS m
)
SELECT it.*
FROM ranked_items itp
inner join Item it on it.id = itp.item_id
WHERE rn = 1 and price < previous_price
Demo here

Getting count of last records of 2 columns SQL

I was looking for a solution for the below mentioned scenario.
So my table structure is like this ; Table name : energy_readings
equipment_id
meter_id
readings
reading_date
1
1
100
01/01/2022
1
1
200
02/01/2022
1
1
null
03/01/2022
1
2
100
01/01/2022
1
2
null
04/01/2022
2
1
null
04/01/2022
2
1
399
05/01/2022
2
2
null
02/01/2022
So from this , I want to get the number of nulls for the last record of same equipment_id and meter_id. (Should only consider the nulls of the last record of same equipment_id and meter_id)
EX : Here , the last reading for equipment 1 and meter 1 is a null , therefore it should be considered for the count. Also the last reading(Latest Date) for equipment 1 and meter 2 is a null , should be considered for count. But even though equipment 2 and meter 1 has a null , it is not the last record (Latest Date) , therefore should not be considered for the count.
Thus , this should be the result ;
equipment_id
Count
1
2
2
1
Hope I was clear with the question.
Thank you!
You can use CTE like below. CTE LatestRecord will get latest record for equipment_id & meter_id. Later you can join it with your current table and use WHERE to filter out record with null values only.
;WITH LatestRecord AS (
SELECT equipment_id, meter_id, MAX(reading_date) AS reading_date
FROM energy_readings
GROUP BY equipment_id, meter_id
)
SELECT er.meter_id, COUNT(1) AS [Count]
FROM energy_readings er
JOIN LatestRecord lr
ON lr.equipment_id = er.equipment_id
AND lr.meter_id = er.meter_id
AND lr.reading_date = er.reading_date
WHERE er.readings IS NULL
GROUP BY er.meter_id
with records as(
select equ_id,meter_id,reading_date,readings,
RANK() OVER(PARTITION BY meter_id,equ_id
order by reading_date) Count
from equipment order by equ_id
)
select equ_id,count(counter)
from
(
select equ_id,meter_id,reading_date,readings,MAX(Count) as counter
from records
group by meter_id,equ_id
order by equ_id
) where readings IS NULL group by equ_id
Explanation:-
records will order data by reading_date and will give counting as 1,2,3..
select max of count from records
select count of counter where reading is null
Partition by will give counting as shown in image
Result

SQL Select Distinct Top5 with Order By and Where

I have a table where Employees can check assets and each of their checks is recorded in a table.
Now I want to extract the 5 last checked Asset_Ids for a given employee. He might have checked the same asset more than once, each check is recorded in a table -EmployeeLog-
Basically my table has 3 columns :
Employee_ID
DateChecked
Asset_ID
1
06/10/2021 10:56:22
1
1
06/10/2021 14:58:25
1
1
02/10/2021 13:56:22
2
1
06/10/2021 08:56:22
1
1
04/10/2021 03:56:22
1
1
06/10/2021 02:56:22
3
1
06/10/2021 15:56:22
2
1
03/10/2021 03:56:22
5
1
06/10/2021 03:56:22
5
I have below query which lists Asset_IDs by check date, but I have to apply distinct and top 5 to this list which I couldn't, any help appreciated.
SELECT Asset_ID
FROM EmployeeLog
WHERE EmployeeID = #Emp_ID AND Asset_ID != '00000000-0000-0000-0000-000000000000'
ORDER BY EmployeeLog.DateChecked Desc
You can do a GROUP BY, and order by first (or last) date.
SELECT Asset_ID
FROM EmployeeLog
WHERE EmployeeID = #Emp_ID AND Asset_ID != '00000000-0000-0000-0000-000000000000'
GROUP BY Asset_ID
ORDER BY MIN(EmployeeLog.DateChecked) Desc
To get the first 5 rows only, do SELECT TOP 5 Asset_ID etc.

How to count over rows and avoid duplicates?

For a university project I have to calculate a kpi based on the data of one table. The table stores data about baskets of a supermarket and the shopped line items and their product category. I have to calculate a number of all product categories of products which were bought in a specific store. So in tables it looks like this:
StoreId BasketID CategoryId
1 1 1
1 1 2
1 1 3
1 2 1
1 2 3
1 2 4
2 3 1
2 3 2
2 3 3
2 4 1
As a result of the query I want a table which counts the distinct product categories over all basket associated to a store.
Something like this:
StoreId Count(CategoryId)
1 4
2 3
If I do a not dynamic statement with hard values, it is working.
select basket_hash, store_id, count(DISTINCT retailer_category_id)
from promo.checkout_item
where store_id = 2
and basket_hash = 123
GROUP BY basket_hash, store_id;
But when I try to write it in a dynamic way, the sql calculates the amount per basket and adds the single amounts together.
select store_id, Count(DISTINCT retailer_category_id)
from promo.checkout_item
group by store_id;
But like this it isn't comparing the categories over all baskets associated to a store and I'm getting duplicates because a category can be in basket 1 and in basket 2.
Can somebody pls help?!
Thx!
As your expected result, Do you want following statement?
SELECT StoreId, COUNT(*)
FROM (
SELECT DISTINCT StoreId, CategoryId
FROM table_name
)
GROUP BY StoreId;
Please, replace "table_name" in statement by your table's name.
I'm not sure what is "dynamic way" meaning.
I'm confused by your requirements. This is what I suppose you mean:
with checkout_item (store_id, basket_hash, retailer_category_id) as (
values
(1,1,1),(1,1,2),(1,1,3),(1,2,1),(1,2,3),
(1,2,4),(2,3,1),(2,3,2),(2,3,3),(2,4,1)
)
select distinct store_id, basket_hash, store_cats, basket_cats
from (
select store_id, basket_hash,
max(store_cats) over (partition by store_id) as store_cats,
max(basket_cats) over (partition by basket_hash) as basket_cats
from (
select store_id, basket_hash,
dense_rank() over (
partition by store_id
order by retailer_category_id
) as store_cats,
dense_rank() over (
partition by basket_hash
order by retailer_category_id
) as basket_cats
from checkout_item
) s
) s
order by 1, 2
;
store_id | basket_hash | store_cats | basket_cats
----------+-------------+------------+-------------
1 | 1 | 4 | 3
1 | 2 | 4 | 3
2 | 3 | 3 | 3
2 | 4 | 3 | 1

Return results where first entry is 1 and all subsequent rows are 0

I m working on weird SQL query
Patient_ID Count order_no
1 1 1
2 1 2
2 0 3
2 0 4
3 1 5
3 0 6
where I need to count the patient as above, for every new patient , the count column is 1.
If repeated , the below entry it should be 0
I m confused how should make that work in SQL
In order to make the first entry 1 and all subsuqent entries 0, I believe you need a ranking with partition by the order number. Please checkout the sqlfiddle below to test results.
http://www.sqlfiddle.com/#!3/4e2e2/17/0
SELECT
patient_id
,CASE WHEN r.rank = 1
THEN 1
ELSE 0
END
, order_number
FROM
(
SELECT
order_number
,patient_id
,ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY order_number)[rank]
FROM
PatientTable
)r