SQL retrieving data NOT IN - asp.net

SELECT ID, Name
FROM dbo.AmenitiesList
WHERE TypeID=#Type and Status = 'Available'
AND ID NOT IN
(SELECT AmenitiesID FROM dbo.ReservationList
WHERE Status = 'Cancelled' AND StartDate between #Arrival and #Departure
or EndDate between #Arrival and #Departure
or #Arrival between StartDate and EndDate
or #Departure between StartDate and EndDate)
This is my query, I want to display all the Available Amenities that the status is 'Cancelled' and the Arrival Date and Departure date is not between in the ArrivalDate and Departure date in Database. But when retrieving data, I didn't get the Amenities available because when the Status is cancelled it triggers the other condition about those in between dates. How to Avoid that?
I want to display Amenities that is Cancelled and also not between ArrivalDate and Departure Date
Thank you in advance guys!

For performance and optimization, consider table variables.
DECLARE #TABLE AS TABLE
(
AmenityID INT PRIMARY KEY CLUSTERED
)
INSERT INTO #TABLE
SELECT AmenitiesID FROM dbo.ReservationList
--Your conditions
--Get values that exist
SELECT * FROM AmentitiesList al
INNER JOIN #Table t on al.AmenityID = t.AmenityID
--Get values that don't
SELECT * FROM AmentitiesList al
LEFT JOIN #Table t on al.AmenityID = t.AmenityID
WHERE t.AmenityID IS NULL
Just because code is shorter, doesn't mean it scales. Left Joins are also a pain...
You could easily get rid of that too by using a table variable.
DECLARE #AmenityList AS TABLE
(
AmenityID INT PRIMARY KEY CLUSTERED
Matched BIT DEFAULT(0)
)
INSERT INTO #AmenityList
Select AmenityID FROM AmentitiesList
UPDATE #AmenityList SET Matched = 1
FROM #AmenitityList al
INNER JOIN #Table t on t.AmentityID = al.AmentityID
SELECT * FROM #AmentityList WHERE Matched = 0

How about this version?
SELECT ID, Name
FROM dbo.AmenitiesList
WHERE TypeID=#Type and Status = 'Available'
AND ID NOT IN
(SELECT AmenitiesID FROM dbo.ReservationList
WHERE Status = 'Cancelled' AND (StartDate between #Arrival and #Departure
or EndDate between #Arrival and #Departure
or #Arrival between StartDate and EndDate
or #Departure between StartDate and EndDate))

SELECT ID, Name
FROM dbo.AmenitiesList
WHERE TypeID=#Type and Status = 'Available'
AND ID NOT IN
(SELECT AmenitiesID FROM dbo.ReservationList
WHERE Status != 'Cancelled' AND Status != 'Check Out' AND ((#Arrival <= EndDate) AND (#Departure >= StartDate)))
This solve my problem! By the way thank you guys for spending time giving information to me! God Bless!

Related

SQLite: Alternative for UPDATE JOIN subquery

I have the following SELECT query in SQLite. I'm struggling to figure out how to convert this to a SQLite-friendly UPDATE statement though... I know SQLite UPDATE does not support JOIN. Thank you!
The query is finding the most recent/maximum date for each employee and adding a column with that date to each individual employee
SELECT
emp.*, maxdate
FROM
employees emp JOIN (
SELECT name as newname, MAX(enddate) AS maxdate
FROM
employees
GROUP BY name) m
ON emp.name = m.newname
ORDER BY maxdate DESC;
Hmm, if I understand correctly, what you want is
UPDATE employees
SET enddate = (
SELECT MAX(enddate)
FROM employees e2
WHERE e2.name = employees.name
);

Return 0 if the date for a certain day does not have values

I'm doing a query to return the number of count records for a certain date.
The problem is when I use the GroupBy by a certain day, If the date have no records then the date for that day will not be shown in the output.
How can I achieve that?
I'm doing something like:
SELECT COUNT(History.Id)
FROM History
INNER JOIN User ON User.Id = History.UserId
WHERE (#StartDate = #NullDate OR History.CreatedOnDate >= #StartDate)
AND (#EndDate = #NullDate OR History.CreatedOnDate <= #EndDate)
GROUP BY History.CreatedOnDat
Example
01-08, 3 records
02-08, 2 records
04-08, 5 records
I need to have 03-08 with 0 records.
Create a temp table with one day per row:
Declare #StartDate datetime = '2016-08-01'
Declare #EndDate datetime = '2016-08-31'
declare #temp table
(
oneday datetime
);
WHILE #StartDate <= #EndDate
begin
INSERT INTO #temp VALUES (#StartDate);
SET #StartDate = Dateadd(Day,1, #StartDate);
end
select * from #temp
Then, simply join your query with this temp table.

SQLite Efficient Running Total

I have a table of transactions in SQLite
number date Category Amount runningBalance
I want the running balance column to have a running sum of the amount column after the table is sorted by Date first and number second.
I can do this with a select when reading. But this table has the potential to get very large and I don't want to recalculate every time. I want to make a trigger where all the transactions following (by date then number) the inserted/edited transaction have their runningBalance value updated.
This will mean that the calculations are reduced... as more recent transactions are likely to be edited more often, and older ones rarely. It also will spread the computation over writes so that reads are near instant.
Can anyone provide assistance on how to set up such a trigger?
so far this is what I have but it does not give desired results. And recalculates all every time. Not just the ones following the change.
CREATE TRIGGER RunningTotal AFTER UPDATE ON Transactions FOR EACH ROW
BEGIN
UPDATE Transactions
SET RunningBalance = (
SELECT (
SELECT sum(Amount)
FROM TopInfo t2
WHERE t2.Date <= t1.Date
)
FROM Transactions t1
);
END;
Thanks!
I've managed to find a way that works. Not sure how efficient it is though. Love to hear if anyone knows a more efficient way to update the Balance column.
CREATE TRIGGER Balance AFTER UPDATE OF Amount ON Transactions FOR EACH ROW
BEGIN
UPDATE Transactions
SET Balance = (
SELECT Balance
FROM (
SELECT TransactionID,
(
SELECT sum(t2.Amount)
FROM Transactions t2
WHERE t2.Date <= t1.Date
ORDER BY Date
)
AS Balance
FROM Transactions t1
WHERE TransactionID = Transactions.TransactionID
ORDER BY Date
)
)
WHERE Transactions.Date >= NEW.Date;
END;
UPDATE:
CREATE TRIGGER Balance AFTER UPDATE OF Amount ON Transactions FOR EACH ROW
BEGIN
UPDATE Transactions
SET Balance = (
SELECT Balance
FROM (
SELECT TransactionID,
(
SELECT sum(t2.Amount)
FROM Transactions t2
WHERE CASE WHEN t2.Date = t1.Date THEN t2.TransactionID <= t1.TransactionID ELSE t2.Date <= t1.Date END
ORDER BY Date,
TransactionID
)
AS Balance
FROM Transactions t1
WHERE TransactionID = Transactions.TransactionID
ORDER BY Date,
TransactionID
)
)
WHERE Transactions.Date >= NEW.Date;
END;
I've Done Some more with running total and have come up with 2 ways. The second is much slower than the first. Any ideas why???
method 1
SELECT TransactionID,Date, Account, Amount,
(SELECT sum(t2.Amount)
FROM Transactions t2
WHERE
CASE WHEN t2.Date = t1.Date
THEN t2.TransactionID <= t1.TransactionID
AND t2.Account == t1.Account
ELSE t2.Date <= t1.Date
AND t2.Account == t1.Account
END
ORDER BY Date, TransactionID)
AS Balance
FROM Transactions t1
ORDER BY Date, TransactionID
Method2
SELECT n.TransactionID, n.Date, n.Account, n.Amount,
SUM(o.Amount) As running_total
FROM Transactions n LEFT JOIN Transactions o
ON (
CASE WHEN o.Date = n.Date
THEN n.TransactionID >= o.TransactionID
AND o.Account == n.Account
ELSE n.Date >= o.Date
AND o.Account == n.Account
END
)
GROUP BY n.Account, n.Date, n.TransactionID
ORDER BY n.Date, n.TransactionID;

Update multiple rows from select statement

I am trying to assign 'A' to [Student Details].group based on this SELECT statement.
SELECT TOP (10) PERCENT [Person Id], [Given Names], Surname, Gpa, [Location Cd]
FROM [Student Details]
WHERE ([Location Cd] = 'PAR')
ORDER BY Gpa DESC
I can't figure out how to use a SELECT statement in an UPDATE statement.
Can someone please explain how to accomplish this?
I am using ASP .NET and MsSQL Server if it makes a difference.
Thanks
I'm assuming you want to update these records and then return them :
SELECT TOP (10) PERCENT [Person Id], [Given Names], Surname, Gpa, [Location Cd]
INTO #temp
FROM [Student Details]
WHERE ([Location Cd] = 'PAR')
ORDER BY Gpa DESC
update [Student Details] set group='A' where [person id] in(select [person id] from #temp)
select * from #temp
I'm also assuming person id is the PK of student details
Try this using CTE (Common Table Expression):
;WITH CTE AS
(
SELECT TOP 10 PERCENT [Group]
FROM [Student Details]
WHERE ([Location Cd] = 'PAR')
ORDER BY Gpa DESC
)
UPDATE CTE SET [Group] = 'A'
Is this you want?
Update top (10) Percent [Student Details] set [group] = 'A'
where [Location Cd] = 'PAR' AND [group] is null

Preventing Max function from using timestamp as part of criteria on a date column in PL/SQL

If I query:
select max(date_created) date_created
on a datefield in PL/SQL (Oracle 11g), and there are records that were created on the same date but at different times, Max() returns only the latest times on that date. What I would like to do is have the times be ignored and return ALL records that match the max date, regardless of their associated timestamp in that column. What is the best practice for doing this?
Edit: what I'm looking to do is return all records for the most recent date that matches my criteria, regardless of varying timestamps for that day. Below is what I'm doing now and it only returns records from the latest date AND time on that date.
SELECT r."ID",
r."DATE_CREATED"
FROM schema.survey_response r
JOIN
(SELECT S.CUSTOMERID ,
MAX (S.DATE_CREATED) date_created
FROM schema.SURVEY_RESPONSE s
WHERE S.CATEGORY IN ('Yellow', 'Blue','Green')
GROUP BY CUSTOMERID
) recs
ON R.CUSTOMERID = recs.CUSTOMERID
AND R.DATE_CREATED = recs.date_created
WHERE R.CATEGORY IN ('Yellow', 'Blue','Green')
Final Edit: Got it working via the query below.
SELECT r."ID",
r."DATE_CREATED"
FROM schema.survey_response r
JOIN
(SELECT S.CUSTOMERID ,
MAX (trunc(S.DATE_CREATED)) date_created
FROM schema.SURVEY_RESPONSE s
WHERE S.CATEGORY IN ('Yellow', 'Blue','Green')
GROUP BY CUSTOMERID
) recs
ON R.CUSTOMERID = recs.CUSTOMERID
AND trunc(R.DATE_CREATED) = recs.date_created
WHERE R.CATEGORY IN ('Yellow', 'Blue','Green')
In Oracle, you can get the latest date ignoring the time
SELECT max( trunc( date_created ) ) date_created
FROM your_table
You can get all rows that have the latest date ignoring the time in a couple of ways. Using analytic functions (preferrable)
SELECT *
FROM (SELECT a.*,
rank() over (order by trunc(date_created) desc) rnk
FROM your_table a)
WHERE rnk = 1
or the more conventional but less efficient
SELECT *
FROM your_table
WHERE trunc(date_created) = (SELECT max( trunc(date_created) )
FROM your_table)

Resources