SQL select column of attributes with latest date [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have a table with multiple tenants and some tenants have an other expiration date, the rest in the table is for every tenant the same. I want to select the tenant with only the latest expiration date.
This is my code:
SELECT DISTINCT
property.scode AS "M nr",
tenant.scode AS "Contract nr",
unit.scode AS "Unit",
commamendments.DTSTART AS "Starting date",
sqft.DTDATE AS "Expiry date",
sqft.DSQFT0 AS "Area"
FROM
property
LEFT JOIN unit ON unit.hproperty = property.hmy
LEFT JOIN unitxref ON unitxref.hunit = unit.hmy
LEFT JOIN commamendments ON commamendments.hmy = unitxref.hamendment
LEFT JOIN tenant ON tenant.hmyperson = commamendments.htenant
JOIN attributes ON attributes.HPROP = property.hmy
JOIN sqft ON sqft.hpointer = unit.hmy
WHERE property.scode = '481'
AND sqft.DSQFT0 != '0'
AND ('9/30/2017 12:00:00 AM' BETWEEN commamendments.DTSTART AND commamendments.DTEND)
ORDER BY commamendments.DTEND`
As output I want a table with
Mnr Contract nr Unit Starting date Expiry date Area
481 1 1 9-10-2017 12-31-2018 400
481 2 2 8-10-2017 12-31-2019 500
.....
What I now receive is:
Mnr Contract nr Unit Starting date Expiry date Area
481 1 1 9-10-2017 12-31-2018 400
481 1 1 9-10-2017 09-20-2018 400
481 2 2 8-10-2017 12-31-2019 500
481 2 2 8-10-2017 1-31-2018 500
.....

Since you didn't specify which RDBMS you are working on and the table schema, then you can do this:
SELECT t1.tenantId, t1.ExpiryDate
FROM tenants AS t1
INNER JOIN
(
SELECT tenantId, MAX(ExpiryDate) AS LatestExpiryDate
FROM tablename
GROUP BY tenantId
) AS t1 ON t1.tenantId = t2.tenantId, t1.ExpiryDate = t2.LatestExpiryDate;
The inner join will give the latest date for each tenant id, and then you can join with the original query to get only those with the latest date.
(You didn't specify the table schema so I had to guess the columns' names, but I hope you got the idea).

Use Row_Number() to find the latest record of your tenants
Select * from (
Select *,Row_number() over(Partition by Tenants order by expirationdate desc) as rn from tablea
) x
Where rn = 1

Related

How to use group by with case statement [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 11 months ago.
Improve this question
I have a table with following fields
CREATE TABLE Tblstock
( ID int , SlNo int, Storage varchar(10), stock int);
insert into Tblstock values
(1, 1, 'STORE', 100),
(2, 1, 'Floor 1', 20),
(3, 2, 'STORE', 2000),
(4, 2, 'Floor 1', 40);
I have to dynamically update the left over quantity in store after it got consumed on floor1, I have written a code to calculate qty in store using below mentioned query,
SELECT (
(SELECT CASE WHEN COUNT(B.SlNo) > 1 OR B.Storage = 'STORE' THEN SUM(B.Stock)END FROM TblStock B GROUP BY B.SlNo) -
(SELECT CASE WHEN COUNT(B.SlNo) > 1 OR B.Storage <> 'STORE' THEN SUM(B.Stock)END FROM TblStock B GROUP BY B.SlNo))
However it is not generating the desired result and throwing error
Can anybody help to write it properly so that I get single value of remaining quantity in store
You just need a straight-forward grouping and conditional aggregation
SELECT
s.SlNo,
Total = SUM(CASE WHEN s.Storage = 'STORE' THEN s.Qty ELSE -s.Qty END)
FROM TblStock s
GROUP BY
s.SlNo;
db<>fiddle
Assuming what you are trying to do is to deduct the quantity (qty) in storage called store by the sum of the rest of the other storage. I could think of a query like this:
select *,
(Qty - (select sum(b.Qty) from tblstock as b
where b.Storage <> 'store'
and b.SINo = a.SINo
group by b.SINo)) as remainingQty
from tblstock as a
where a.Storage = 'store' group by a.SINo
The query above, with the following input:
ID
SINo
Storage
Qty
1
1
store
100
2
1
floor 1
20
3
1
floor 2
30
4
2
store
100
5
2
floor 1
40
6
2
floor 2
50
It produces the following output:
ID
SINo
Storage
Qty
remainingQty
1
1
store
100
50
4
2
store
100
10
You can find the SQLFiddle here.
Note:
If you are want to avoid subquery and have the urge to chug in join fiddle:
select a.id,
a.SINo,
a.Storage,
a.Qty,
c.Qty,
(a.Qty - c.Qty) as remainingQty
from tblstock as a
join
(select b.SINo,
sum(b.Qty) as Qty
from tblstock as b
where b.Storage <> 'store'
group by b.SINo) as c
on c.SINo = a.SINo
where a.Storage = 'store' group by a.SINo

update based on multiple rows in sql [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
PART LATESTPART RATE LATESTMONTHSALE status
A X 100 2019-06-01 N
B X 100 2019-07-01 N
C Y 200 2019-08-01 N
D Y 150 2019-08-01 N
E X 100 2019-09-01 N
update status as "Y" of PART when LATESTPART is same and RATE minimum
Eg. for PART C,D LATESTPART is same(Y) and rate of 'PART' D is minimum(150) then update part D status "Y".
If rate is same then check LATESTMONTHSALE. Update status of the PART having lastest month.
Eg. for PART A,B,E LATESTPART is same(X) and rate is also same then update PART E because 2019-09-01 is latest date.
i want result as.
PART LATESTPART RATE LATESTMONTHSALE status
A X 100 JUN_19 N
B X 100 JUL_19 N
C Y 200 AUG_19 N
D Y 150 AUG_19 Y
E X 100 SEP_19 Y
I think that you can do this with a correlated subquery that filters on the latest records per (part, latestpart) tuple and a not exists condition that filters on the record that has the lowest rate.
update mytable t set status = 'Y'
where
t.latestmonthsale = (
select max(t1.latestmonthsale)
from mytable t1
where t1.part = t.part and t1.latestpart = t.latestpart
)
and not exists (
select 1
from mytable t1
where
t1.part = t.part
and t1.latestpart = t.latestpart
and t1.latestmonthsale = t.latestmonthsale
and t1.rate < t.rate
)
In SQLServer, you can also do this with row_number() and an updatable cte:
with cte as (
select
status,
row_number()
over(partition by part, latestpart order by latestmonthsale desc, rate) rn
from mytable
)
update cte set status = 'Y' where rn = 1

How do I get the max records of a max subset in SQL [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have the following tables:
Training Occurrence
Id Training Id Due Date
5 1 09/01/2018
6 1 09/15/2018
7 2 09/01/2018
Training Occurrence User
Id Training Material Occurrence Id User Id
1 5 'Chad'
2 5 'Chad'
3 6 'Chad'
4 6 'Chad'
5 7 'Chad'
My query needs to get the newest Training Material Occurrence User record of the newest Training Material Occurrence table. So if I pass in the user 'Chad'
I would want to see:
Id Occurrence Id User Training Id Due Date
4 6 'Chad' 1 09/15/2018
5 7 'Chad' 2 09/01/2018
Here is my query:
SELECT tmou.*, tmo.TrainingMaterialId, tmo.DueDate
FROM dbo.TrainingMaterialOccurrenceUser as tmou
INNER JOIN dbo.TrainingMaterialOccurrence as tmo on
tmou.TrainingMaterialOccurrenceId = tmo.Id
AND tmou.Id IN (SELECT MAX(tmou.Id)
FROM dbo.TrainingMaterialOccurrenceUser as tmou
WHERE tmou.UserId = #UserId
AND tmou.TrainingMaterialOccurrenceId IN (SELECT MAX(tmo.Id) as occurrenceId
FROM dbo.TrainingMaterialOccurrence as tmo
WHERE tmo.Id IN (Select TrainingMaterialOccurrenceId FROM dbo.TrainingMaterialOccurrenceUser as tmou1 WHERE tmou1.UserId = #UserId)
GROUP BY tmo.TrainingMaterialId)
GROUP BY tmou.TrainingMaterialOccurrenceId)
As you can see this is a mess. Any ideas on how I can clean this up.
Rank your rows with ROW_NUMBER:
SELECT Id, TrainingMaterialOccurrenceId, UserId, TrainingMaterialId, DueDate
FROM
(
SELECT
tmou.Id,
tmou.TrainingMaterialOccurrenceId,
tmou.UserId,
tmo.TrainingMaterialId,
tmo.DueDate,
ROW_NUMBER() OVER(PARTITION BY tmo.TrainingMaterialId
ORDER BY tmo.DueDate DESC,
tmo.Id DESC,
tmou.TrainingMaterialOccurrenceId DESC,
tmou.Id DESC) AS rn
FROM dbo.TrainingMaterialOccurrenceUser as tmou
INNER JOIN dbo.TrainingMaterialOccurrence as tmo
ON tmo.Id = tmou.TrainingMaterialOccurrenceId
)
WHERE rn = 1;

Group By from two tables [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a requirement to show a report in the following format from the two different tables as shown below, the below report should count the order numbers by branch.
===================================================================
Branch OrdersCountInTable1 OrdersCountInTable2
===================================================================
100 5 2
200 10 10
300 12 11
how can i achieve this using a sqlquery?
Following are the columns in the tables:
Table1:
________
- Branch
- OrderNo
Table2
__________
- Branch
- OrderNo
Table1 Data:
===============================
Branch OrderNo
===============================
100 1000
100 1001
200 2001
100 1003
Table2 Data:
===============================
Branch OrderNo
===============================
100 1000
200 2001
100 1003
We just want to reconcile orders from both the tables!!
Thanks for any valuable feedbacks.
One more or less generic way to do it
SELECT COALESCE(t1.branch, t2.branch) branch,
COALESCE(t1.ordercount, 0) OrdersCountInTable1,
COALESCE(t2.ordercount, 0) OrdersCountInTable2
FROM
(
SELECT branch, COUNT(orderno) ordercount
FROM Table1
GROUP BY branch
) t1 FULL JOIN
(
SELECT branch, COUNT(orderno) ordercount
FROM Table2
GROUP BY branch
) t2
ON t1.branch = t2.branch
Assumption is that tables may not have entries for all branches. That's why FULL JOIN is used.
Do like this using SUM aggregate function and UNION ALL operator
SELECT Branch,
SUM( CASE tag WHEN 'table1' THEN 1 ELSE 0 END) as OrdersCountInTable1,
SUM( CASE tag WHEN 'table2' THEN 1 ELSE 0 END) as OrdersCountInTable2
FROM
(
SELECT Branch,'table1' as tag
FROM Table1
UNION ALL
SELECT Branch,'table2' as tag
FROM Table2
) z
GROUP BY Branch
ORDER BY Branch
Try it with a union nested query:
select
Branch, count(Orders1) OrdersCountInTable1, count(Orders2) OrdersCountInTable2
from (
select Branch,OrderNo Orders1,NULL Orders2 from Table1
union
select Branch,NULL Orders1,OrderNo Orders2 from Table2
) t
group by Branch

How do I fix this SQL query returning improper values?

I am writing an SQL query which will return a list of auctions a certain user is losing, like on eBay.
This is my table:
bid_id bid_belongs_to_auction bid_from_user bid_price
6 7 1 15.00
8 7 2 19.00
13 7 1 25.00
The problematic area is this (taken from my full query, placed at the end of the question):
AND EXISTS (
SELECT 1
FROM bids x
WHERE x.bid_belongs_to_auction = bids.bid_belongs_to_auction
AND x.bid_price > bids.bid_price
AND x.bid_from_user <> bids.bid_from_user
)
The problem is that the query returns all the auctions on which there are higher bids, but ignoring the user's even higher bids.
So, an example when the above query works:
bid_id bid_belongs_to_auction bid_from_user bid_price
6 7 1 15.00
7 7 2 18.00
In this case, user 1 is returned as losing the auction, because there is another bid higher than the users bid.
But, here is when the query doesn't work:
bid_id bid_belongs_to_auction bid_from_user bid_price
6 7 1 15.00
8 7 2 19.00
13 7 1 25.00
In this case, user 1 is incorrectly returned as losing the auction, because there is another bid higher than one of his previous bids, but the user has already placed a higher bid over that.
If it's important, here's my full query, but I think it won't be necessary to solve the aforementioned problem, but I'm posting it here anyway:
$query = "
SELECT
`bid_belongs_to_auction`,
`auction_unixtime_expiration`,
`auction_belongs_to_hotel`,
`auction_seo_title`,
`auction_title`,
`auction_description_1`
FROM (
SELECT
`bid_belongs_to_auction`,
`bid_from_user`,
MAX(`bid_price`) AS `bid_price`,
`auctions`.`auction_enabled`,
`auctions`.`auction_unixtime_expiration`,
`auctions`.`auction_belongs_to_hotel`,
`auctions`.`auction_seo_title`,
`auctions`.`auction_title`,
`auctions`.`auction_description_1`
FROM `bids`
LEFT JOIN `auctions` ON `auctions`.`auction_id`=`bids`.`bid_belongs_to_auction`
WHERE `auction_enabled`='1' AND `auction_unixtime_expiration` > '$time' AND `bid_from_user`='$userId'
AND EXISTS (
SELECT 1
FROM bids x
WHERE x.bid_belongs_to_auction = bids.bid_belongs_to_auction
AND x.bid_price > bids.bid_price
AND x.bid_from_user <> bids.bid_from_user
)
GROUP BY `bid_belongs_to_auction`
) AS X
WHERE `bid_from_user`='$userId'
";
Here's a different approach:
$query = "
SELECT
`max_bids`.`bid_belongs_to_auction`,
`auctions`.`auction_unixtime_expiration`,
`auctions`.`auction_belongs_to_hotel`,
`auctions`.`auction_seo_title`,
`auctions`.`auction_title`,
`auctions`.`auction_description_1`
FROM `auctions`
INNER JOIN (
SELECT
`bid_belongs_to_auction`,
MAX(`bid_price`) AS `auction_max_bid`,
MAX(CASE `bid_from_user` WHEN '$userId' THEN `bid_price` END) AS `user_max_bid`
FROM `bids`
GROUP BY `bid_belongs_to_auction`
) AS `max_bids` ON `auctions`.`auction_id` = `max_bids`.`bid_belongs_to_auction`
WHERE `auctions`.`auction_enabled`='1'
AND `auctions`.`auction_unixtime_expiration` > '$time'
AND `max_bids`.`user_max_bid` IS NOT NULL
AND `max_bids`.`user_max_bid` <> `max_bids`.`auction_max_bid`
";
Basically, when you are retrieving the max bids for all the auctions, you are also retrieving the specific user's max bids along. Next step is to join the obtained list to the auctions table and apply an additional filter on the user's max bid being not equal to the auction's max bid.
Note: the `max_bids`.`user_max_bid` IS NOT NULL condition might be unnecessary. It would definitely be so in SQL Server, because the non-nullness would be implied by the `max_bids`.`user_max_bid` <> `max_bids`.`auction_max_bid` condition. I'm not sure if it's the same in MySQL.
Untested, but this is how I would approach it. Ought to perform OK if there's an index on userid and also one on auctionid.
select OurUserInfo.auctionid, OurUserInfo.userid,
OurUserInfo.ourusersmaxbid, Winningbids.TopPrice
from
(
select A.auctionid, A.userid, max(A.price) as OurUsersMaxBid
from auctions A where userid = ?
group by A.auctionid, A.userid
) as OurUserInfo
inner join
(
-- get the current winning bids for all auctions in which our user is bidding
select RelevantAuctions.auctionid, max(auctions.price) as TopPrice
from auctions inner join
(
select distinct auctionid from auctions where userid = ? -- get our user's auctions
) as RelevantAuctions
on auctions.auctionid = RelevantAuctions.auctionid
group by RelevantAuctions.auctionid
) as WinninBids
on OurUserInfo.auctionid = winningbids.auctionid
where WinninBids.TopPrice > OurUserInfo.ourusersmaxbid
Instead of
SELECT 1
FROM bids x
WHERE x.bid_belongs_to_auction = bids.bid_belongs_to_auction
AND x.bid_price > bids.bid_price
AND x.bid_from_user <> bids.bid_from_user
try this:
SELECT 1
FROM (SELECT BID_ID,
BID_BELONGS_TO_AUCTION,
BID_FROM_USER,
BID_PRICE
FROM (SELECT BID_ID,
BID_BELONGS_TO_AUCTION,
BID_FROM_USER,
BID_PRICE,
RANK ()
OVER (
PARTITION BY BID_BELONGS_TO_AUCTION, BID_FROM_USER
ORDER BY BID_PRICE DESC)
MY_RANK
FROM BIDS)
WHERE MY_RANK = 1) x
WHERE x.bid_belongs_to_auction = bids.bid_belongs_to_auction
AND x.bid_price > bids.bid_price
AND x.bid_from_user <> bids.bid_from_user;