Join & Subquery to calculate Minimum datediff - sql

I have 2 SQL tables, one for subscribers (ID, Name), second for subscribers_Upgrades [Subscriber_ID (FK), Upgrade_Level, Upgrade_Date)
(There are 7 upgrade levels)
I need a query to get the top 10 subscribers who upgraded in the shortest period and Upgrade_Level, and Upgrade Date for specific Upgrade_Level (any one of the available 7 Upgrade level), and within specific period of time
We can, for example supply the 2 conditions like
Where Upgrade_Level = 3 and Upgrade_Date between '01-April-2014' and '20-May-2016'

What you mean shortest period? Who have upgraded in earliest time in upgrade_date order?
SELECT TOP 10 s.ID,
s.Name,
su.UpgradeLevel,
su.UpgradeDate
FROM Subscribers s
INNER JOIN SubscribersUpgrades su on s.ID = su.SubscriberId
WHERE su.UpgradeLevel = 3 AND su.UpgradeDate BETWEEN '01-April-2014' AND '20-May-2016'
ORDER BY su.UpgradeDate ASC
UPDATE
If you need data only for 2 upgrade level (level 2 and 3) this should work -
SELECT TOP 10 s.Name, DATEDIFF(dd,t1.UpgradeDate,t2.UpgradeDate) UpgradePeriodInDays FROM
(SELECT su.SubscriberId, su.UpgradeDate FROM SubscribersUpgrades su
WHERE su.UpgradeLevel = 2 ) t1
INNER JOIN (SELECT su.SubscriberId, su.UpgradeDate FROM SubscribersUpgrades su
WHERE su.UpgradeLevel = 3) t2 on t1.SubscriberId = t2.SubscriberId
INNER JOIN Subscribers s on t1.SubscriberId = s.ID
WHERE t2.UpgradeDate BETWEEN '01-June-2016' AND '20-July-2016'
ORDER BY DATEDIFF(dd,t1.UpgradeDate,t2.UpgradeDate) ASC

Related

How to get Odoo Inventory adjustment value through SQL

I am working on a custom stock valuation module and in one model I am trying to get adjustment value for a lot - product - warehouse wise of the previous day.
QUERY 1
SELECT COUNT(*)
FROM
(
SELECT stock_inventory.date AS stock_adjustment_date,
stock_move_line.lot_id,
stock_move_line.product_id,
SUM(stock_move_line.qty_done) total_stock_adjustment
FROM stock_move_line
LEFT JOIN stock_move ON stock_move_line.move_id = stock_move.id
LEFT JOIN stock_inventory ON stock_move.inventory_id = stock_inventory.id
WHERE stock_move.inventory_id IS NOT NULL
AND stock_move_line.location_id = 5
AND stock_move_line.location_dest_id = 13
AND stock_move_line.lot_id IS NOT NULL
GROUP BY stock_move_line.lot_id, stock_move_line.product_id, stock_inventory.date
ORDER BY total_stock_adjustment DESC
)
testTable;
QUERY 2
SELECT COUNT(*)
FROM
(
SELECT stock_inventory.date AS stock_adjustment_date,
stock_move_line.lot_id,
stock_move_line.product_id,
SUM(stock_move_line.qty_done) total_stock_adjustment
FROM stock_move_line
LEFT JOIN stock_move ON stock_move_line.move_id = stock_move.id
LEFT JOIN stock_inventory ON stock_move.inventory_id = stock_inventory.id
WHERE stock_move.inventory_id IS NOT NULL
AND stock_move_line.location_id = 13
AND stock_move_line.location_dest_id = 5
AND stock_move_line.lot_id IS NOT NULL
GROUP BY stock_move_line.lot_id, stock_move_line.product_id, stock_inventory.date
ORDER BY total_stock_adjustment DESC
)
testTable;
Why these both queries returning same count 14,849 ?
13 is the warehouse ID and 5 is the virtual location used for adjustment. What I am doing wrong here?

SQL Queries Returning Non-equivalent Results and Different Counts Every Run

So I have 2 SQL queries both including the same variable: basically (n_orders and orders_count) should return the same exact results. Problem is:
the 2 columns are not always equivalent for all values
the count of different values changes every run
so first run could be that 20 rows have different (n_orders, orders_count) values then 2nd run says count of different values is 56 for example and so on with changing counts every run.
Query 1:
SELECT product_id,
packing_unit_id,
count(DISTINCT product_sales_order.sales_order_id)
FROM product_sales_order
WHERE product_sales_order.created_at::date BETWEEN '{start}' AND '{end}'
GROUP BY 1, 2
ORDER BY product_id, packing_unit_id
Query 2:
select kpis.*, lr.lr
FROM
(SELECT product_sales_order.product_id,
product_sales_order.packing_unit_id,
count(DISTINCT product_sales_order.sales_order_id) AS orders_count,
count(DISTINCT sales_orders.retailer_id) AS retailers_count,
count(DISTINCT product_sales_order.sales_order_id)*1.0 / count(DISTINCT sales_orders.retailer_id) AS frequency,
(count(DISTINCT sales_orders.retailer_id)*1.0 /(SELECT count(DISTINCT sales_orders.retailer_id) AS month_retailers
FROM sales_orders
JOIN retailers on retailers.id = sales_orders.retailer_id
WHERE sales_orders.created_at::Date BETWEEN '{start}' AND '{end}'
AND sales_orders.sales_order_status_id = 6
AND retailers.is_market_type_private = false)) AS reach,
sum(product_sales_order.total_price) AS nmv,
(sum(product_sales_order.total_price)*1.0 / (SELECT sum(product_sales_order.total_price) AS month_nmv
FROM product_sales_order
WHERE product_sales_order.created_at::Date BETWEEN '{start}' AND '{end}'
AND product_sales_order.purchased_item_count <> 0)) AS contribution,
sum(product_sales_order.purchased_item_count * product_sales_order.basic_unit_count) AS bskt_size,
sum(product_sales_order.total_price)*1.0 / count(DISTINCT product_sales_order.sales_order_id) AS avg_ts,
sum(product_sales_order.total_price)*1.0 / count(DISTINCT sales_orders.retailer_id) AS nmv_p_retailer
FROM product_sales_order
LEFT JOIN sales_orders ON sales_orders.id = product_sales_order.sales_order_id
LEFT JOIN products ON products.id = product_sales_order.product_id
LEFT JOIN retailers on retailers.id = sales_orders.retailer_id
WHERE product_sales_order.created_at::date BETWEEN '{start}' AND '{end}'
GROUP BY 1,2
ORDER BY product_sales_order.product_id, product_sales_order.packing_unit_id, orders_count
) as kpis
LEFT JOIN (
SELECT performance.lost_revenue.product_id,
sum(performance.lost_revenue.lost_revenue) as lr
FROM performance.lost_revenue
WHERE performance.lost_revenue.created_at::Date between '{start}' AND '{end}'
GROUP BY 1
)as lr on lr.product_id = kpis.product_id
What could be corrected regarding the structure of the 2nd SQL query to make it yield the same results for orders_count?
Why does different values count return different results every run?

where statement execute before inner join

I'm trying to grab the first instance of each result with a sysAddress of less than 4. However my statement currently grabs the min(actionTime) result first before applying the where sysAddress < 4. I'm trying to have the input for the inner join as the where sysAddress < 4 however i cant seem to figure out how to do it.
Should i be nesting it all differently? I didnt want to create an additional layer of table joins. Is this possible? I'm a bit lost at all the answers ive found.
SELECT
tblHistoryObject.info,
tblHistory.actionTime,
tblHistoryUser.userID,
tblHistoryUser.firstName,
tblHistoryUser.surname,
tblHistory.eventID,
tblHistoryObject.objectID,
tblHistorySystem.sysAddress
FROM tblHistoryObject
JOIN tblHistory
ON (tblHistory.historyObjectID = tblHistoryObject.historyObjectID)
JOIN tblHistorySystem
ON (tblHistory.historySystemID = tblHistorySystem.historySystemID)
JOIN tblHistoryUser
ON (tblHistory.historyUserID = tblHistoryUser.historyUserID)
INNER JOIN (SELECT
MIN(actionTime) AS recent_date,
historyObjectID
FROM tblHistory
GROUP BY historyObjectID) AS t2
ON t2.historyObjectID = tblHistoryObject.historyObjectID
AND tblHistory.actionTime = t2.recent_date
WHERE sysAddress < 4
ORDER BY actionTime ASC
WITH
all_action_times AS
(
SELECT
tblHistoryObject.info,
tblHistory.actionTime,
tblHistoryUser.userID,
tblHistoryUser.firstName,
tblHistoryUser.surname,
tblHistory.eventID,
tblHistoryObject.objectID,
tblHistorySystem.sysAddress,
ROW_NUMBER() OVER (PARTITION BY tblHistoryObject.historyObjectID
ORDER BY tblHistory.actionTime
)
AS historyObjectID_SeqByActionTime
FROM
tblHistoryObject
INNER JOIN
tblHistory
ON tblHistory.historyObjectID = tblHistoryObject.historyObjectID
INNER JOIN
tblHistorySystem
ON tblHistory.historySystemID = tblHistorySystem.historySystemID
INNER JOIN
tblHistoryUser
ON tblHistory.historyUserID = tblHistoryUser.historyUserID
WHERE
tblHistorySystem.sysAddress < 4
)
SELECT
*
FROM
all_action_times
WHERE
historyObjectID_SeqByActionTime = 1
ORDER BY
actionTime ASC
This does exactly what your original query did, without trying to filter by action_time.
Then it appends a new column, using ROW_NUMBER() to generate sequences from 1 for each individual tblHistoryObject.historyObjectID. Then it takes only the rows where this sequence value is 1 (the first row per historyObjectID, when sorted in action_time order).

How to output results of multiple queries together?

I want to display result of 3 selects together in one window, in the same time.
First:
SELECT sum(r.punkty)
,r.id_kierowcy
FROM wyniki AS r
INNER JOIN wyscigi AS w ON r.id_wyscigu = w.id_wyscigu
WHERE w.rok = 2006
GROUP BY r.id_kierowcy
ORDER BY sum(r.punkty) DESC limit 1
Second:
SELECT sum(r.punkty)
,r.id_kierowcy
FROM wyniki AS r
INNER JOIN wyscigi AS w ON r.id_wyscigu = w.id_wyscigu
WHERE w.rok = 2000
GROUP BY r.id_kierowcy
ORDER BY sum(r.punkty) DESC limit 1
Third:
SELECT sum(r.punkty)
,r.id_kierowcy
FROM wyniki AS r
INNER JOIN wyscigi AS w ON r.id_wyscigu = w.id_wyscigu
WHERE w.rok = 2012
GROUP BY r.id_kierowcy
ORDER BY sum(r.punkty) DESC limit 1
In brief there is one difference in the selects, that is WHERE [2000, 2006, 2012]
Is the way to connect these selects? I must display them as one result set
EDIT: I will try to explain my exercise.
I have 2 tables:
Results and races.
Results contains 3 columns:
id_driver
/points
/id_race
Races contains 3 columns:
id_race
/year
/place
Races are between 2000 and 2012 years
I need to do classification of races in the 2000, 2006, 2012 and establish which one driver(id_driver) won each year. So I'm trying to do like that
SELECT sum(r.points)
,r.id_driver
FROM results AS r
INNER JOIN races AS x ON r.id_race = x.id_race
WHERE x.year = 2012
GROUP BY r.id_driver
ORDER BY sum(r.points) DESC limit 1
and the same for 2006 and 2000, but i need to display that as one result set, that is my problem I dont know how to connect it.

How get specific rows in grouped result

i need to group some data but because there are 4 store images , sql query return 4 result for every store. How can i get only one for a store by using sql query ?
select s.name,si.SHOP_IMG_PATH,count(*) amount from stab t
inner join shop s on (s.shop_id = t.shop_id)
inner join SHOP_IMG si on (s.shop_id= si.SHOP_ID)
where t.acct_id = 111 and t.CR_DATE >= sysDate - 1
group by s.name,si.SHOP_IMG_PATH
order by 3 desc,1 asc
As you see below image there a re 4 images so query can give random image
You are grouping by s.name, si.SHOP_IMG_PATH it will consider all possible combination of s.name, si.SHOP_IMG_PATH as separate you need to keep group by only s.name
Try this
SELECT a.NAME, a.PATH, a.AMOUNT
FROM (select
s.name AS 'NAME', si.SHOP_IMG_PATH AS 'PATH', count(*) AS 'AMOUNT',
ROW_NUMBER() OVER(PARTITION BY s.name
ORDER BY type si.SHOP_IMG_PATH) AS rk
from
stab t
inner join shop s on (s.shop_id = t.shop_id)
inner join SHOP_IMG si on (s.shop_id= si.SHOP_ID)
where t.acct_id = 111 and t.CR_DATE >= sysDate - 1
group by s.name
order by 3 desc,1 asc) a
WHERE a.rk = 1;
Alternative
You will get result but this is just a workaround and easy alternative to your problem but not a good one.
select s.name AS 'NAME', min(si.SHOP_IMG_PATH) AS 'PATH', count(*) AS 'AMOUNT',
from
stab t
inner join shop s on (s.shop_id = t.shop_id)
inner join SHOP_IMG si on (s.shop_id= si.SHOP_ID)
where t.acct_id = 111 and t.CR_DATE >= sysDate - 1
group by s.name
order by 3 desc,1 asc
This second query will return result as per your need
group by s.name, si.SHOP_IMG_PATH
You're telling it to differentiate them according to SHOP_IMG_PATH. Hence, it shows 4 results, one for each of those.
You'll have to drop SHOP_IMG_PATH from the select clause, if you won't let it use it.
Edit
Got your comment. What you're looking for is random aggregation. This is achieved diferently on different SQL engines. Google around for the one you're using.
If it's Oracle, as indicated by the question tag, here
I solved my problem by using below query,
select s.name,t.shop_id,(select min(SHOP_IMG_PATH) from SHOP_IMG si where shop_id =t.shop_id),count(*) amount from stab t
inner join shop s on (s.shop_id = t.shop_id)
where t.acct_id = 111 and t.CR_DATE >= sysDate - 1
group by s.name,t.shop_id
order by 4 desc,1 asc