How to add Order by in sql query - sql

update Room set Status = case
when Room_Rev.In_DateTime IS NOT NULL and Room_Rev.Out_DateTime IS NULL
then 'U'
when Room_Rev.In_DateTime IS NOT NULL and Room_Rev.Out_DateTime IS NOT NULL
then 'A'
when Room.Status!='R' and Room.Status!='U' and Room.Status!='A'
then Room.Status
else 'R'
end
FROM Room JOIN Room_Rev
ON Room.Room_ID=Room_Rev.Room_ID
and
((Room_Rev.Start_Date >= '2015-03-22' and Room_Rev.End_Date <= '2015-03-22')
OR
(Room_Rev.Start_Date<= '2015-03-22' and Room_Rev.End_Date> '2015-03-22')
OR
(Room_Rev.Start_Date< '2015-03-22' and Room_Rev.End_Date>= '2015-03-22'))
How to add order by Rev_ID desc in the query?
There are two table which is Room and Room_Rev,
they are one to many relationship
The last two row ROM0006 already fill the In_DateTime and Out_DateTime,
thus it regard check out,
and the last row insert new reservation,
the In_DateTime is null
thus i need the query return 'R' (Reserved status)

As one of the possible solutions I suggest a nested query instead of a join in UPDATE statement. The logic of the update is not completely clear to me, so I leave the final update for OP to correct order of sorting (Note I used top 1 and order by room_ID in the nested SELECT statement). However, this approach allows to handle all usual techniques applicable for a SELECT.
update Room set Status = (select TOP 1 case
when Room_Rev.In_DateTime IS NOT NULL and Room_Rev.Out_DateTime IS NULL
then 'U'
when Room_Rev.In_DateTime IS NOT NULL and Room_Rev.Out_DateTime IS NOT NULL
then 'A'
when Room.Status!='R' and Room.Status!='U' and Room.Status!='A'
then Room.Status
else 'R'
end
FROM Room_Rev
WHERE Room.Room_ID=Room_Rev.Room_ID
and
((Room_Rev.Start_Date >= '2015-03-22' and Room_Rev.End_Date <= '2015-03-22')
OR
(Room_Rev.Start_Date<= '2015-03-22' and Room_Rev.End_Date> '2015-03-22')
OR
(Room_Rev.Start_Date< '2015-03-22' and Room_Rev.End_Date>= '2015-03-22'))
ORDER BY Room_Rev.Room_Id
)
PS. As a piece of advise I still assume that such approach is not valid. It prevents proper normalization of data. You'd rather have this information always queried dynamically when required, instead of writing static value to ROOM.status

Related

Query that detects difference between accounts/loads from TODAY and YESTERDAY

GOAL: DETECT any difference between yesterday's table loads and today's loads. Each load loads values of data that are associated with bank accounts. So I need a query that returns each individual account that has a difference, with the value in the column name.
I need data from several columns that are located from two different tables. AEI_GFXAccounts and AEI_GFXAccountSTP. Each time the table is loaded, it has a "run_ID" that is incremented by one. So it needs to be compared to MAX(run_id) and MAX(run_id) -1.
I have tried the following queries. All this query does is return all the columns I need. I now need to implement logic that runs these queries WHERE runID = MAX(runID). Then run it again where run_ID = Max(runID) -1. Compare the two tables, show the differences that can be displayed under columns like SELECT AccountBranch WHERE MAX(Run_ID) -1 AS WAS. etc. and another custom named column as 'IS NOW' etc for each column.
SELECT AEI_GFXAccounts.AccountNumber,
AccountBranch,
AccountName,
AccountType,
CostCenter,
TransactionLimit,
ClientName,
DailyCumulativeLimit
FROM AEI_GFXAccounts
JOIN AEI_GFXAccountSTP
ON (AEI_GFXAccounts.feed_id = AEI_GFXAccountSTP.feed_id
and AEI_GFXAccounts.run_id = AEI_GFXAccountSTP.run_id)
I use something similar to this to detect changes for a logging system:
WITH data AS (
SELECT
a.run_id,
a.AccountNumber,
?.AccountBranch,
?.AccountName,
?.AccountType,
?.CostCenter,
?.TransactionLimit,
?.ClientName,
?.DailyCumulativeLimit
FROM
AEI_GFXAccounts a
INNER JOIN AEI_GFXAccountSTP b
ON
a.feed_id = b.feed_id and
a.run_id = b.run_id
),
yest AS (
SELECT * FROM data WHERE run_id = (SELECT MAX(run_id)-1 FROM AEI_GFXAccounts)
),
toda AS (
SELECT * FROM data WHERE run_id = (SELECT MAX(run_id) FROM AEI_GFXAccounts)
)
SELECT
CASE WHEN COALESCE(yest.AccountBranch, 'x') <> COALESCE(toda.AccountBranch, 'x') THEN yest.AccountBranch END as yest_AccountBranch,
CASE WHEN COALESCE(yest.AccountBranch, 'x') <> COALESCE(toda.AccountBranch, 'x') THEN toda.AccountBranch END as toda_AccountBranch,
CASE WHEN COALESCE(yest.AccountName, 'x') <> COALESCE(toda.AccountName, 'x') THEN yest.AccountName END as yest_AccountName,
CASE WHEN COALESCE(yest.AccountName, 'x') <> COALESCE(toda.AccountName, 'x') THEN toda.AccountName END as toda_AccountName,
...
FROM
toda INNER JOIN yest ON toda.accountNumber = yestaccountNumber
Notes:
You didn't say which table some of your columns are from. I've prefixed them with ?. - replace these with a. or as. respectively (always good practice to fully qualify all your column aliases)
When you're repeating out the pattern in the bottom select (above ...) choose data for the COALESCE that will not appear in the column. I'm using COALESCE as a quick way to avoid having to write CASE WHEN a is null and b is not null or b is null and a is not null or a != b, but the comparison fails if accountname (for example) was 'x' yesterday and today it is null, because the null becomes 'x'. If you pick data that will never appear in the column then the check will work out because nulls will be coalesced to something that can never appear in the real data, and hence the <> comparison will work out
If you don't care when a column goes to null today from a value yesterday, or was null yesterday but is a value today, you can ditch the coalesce and literally just do toda.X <> yest.X
New accounts today won't show up until tomorrow. If you want them to show up do toda LEFT JOIN yest .... Of course all their properties will show as new ;)
This query returns all the accounts regardless of whether any changes have been made. If you only want a list of accounts with changes you'll need a where clause that is similar to your case whens:
WHERE
COALESCE(toda.AccountBranch, 'x') <> COALESCE(yest.AccountBranch, 'x') OR
COALESCE(toda.AccountName, 'x') <> COALESCE(yest.AccountName, 'x') OR
...
Do you have a date field? If so you can use Row_Number partitioned by your accounts. Exclude all accounts that have a max of 1 row 'New accounts", and then subtract the Max(rownumber) of each account's load by the Max(rownumber)-1's load. Only return accounts where this returned load is >0.You can also use the lag function to grab the previous accounts load instead of Max(rownumber)-1

the below select statement takes a long in running

This select statement takes a long time running, after my investigation I found that the problem un subquery, stored procedure, please I appreciate your help.
SELECT DISTINCT
COKE_CHQ_NUMBER,
COKE_PAY_SUPPLIER
FROM
apps.Q_COKE_AP_CHECKS_SIGN_STATUS_V
WHERE
plan_id = 40192
AND COKE_SIGNATURE__A = 'YES'
AND COKE_SIGNATURE__B = 'YES'
AND COKE_AUDIT = 'YES'
AND COKE_CHQ_NUMBER NOT IN (SELECT DISTINCT COKE_CHQ_NUMBER_DELIVER
FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V
WHERE UPPER(COKE_CHQ_NUMBER_DELIVER_STATUS) <> 'DELIVERED')
AND COKE_CHQ_NUMBER NOT IN (SELECT COKE_CHQ_NUMBER_DELIVER
FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V)
Well there are a few issues with your SELECT statement that you should address:
First let's look at this condition:
COKE_CHQ_NUMBER NOT IN (SELECT DISTINCT COKE_CHQ_NUMBER_DELIVER
FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V
WHERE UPPER(COKE_CHQ_NUMBER_DELIVER_STATUS) <> 'DELIVERED')
First you select DISTINCT cheque numbers with a not delivered status then you say you don't want this. Rather than saying I don't want non delivered it is much more readable to say I want delivered ones. However this is not really an issue but rather it would make your SELECT easier to read and understand.
Second let's look at your second cheque condition:
COKE_CHQ_NUMBER NOT IN (SELECT COKE_CHQ_NUMBER_DELIVER
FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V)
Here you want to exclude all cheques that have an entry in Q_COKE_AP_CHECKS_DELIVERY_ST_V. This makes your first DISTINCT condition redundant as whatever cheques numbers will bring back would be rejected by this second condition of yours. I do't know if Oracle SQL engine is clever enough to work out this redundancy but this could cause your slowness as SELECT distinct can take longer to run
In addition to this if you don't have them already I would recommend adding the following indexes:
CREATE INDEX index_1 ON q_coke_ap_checks_sign_status_v(coke_chq_number, coke_pay_supplier);
CREATE INDEX index_2 ON q_coke_ap_checks_sign_status_v(plan_id, coke_signature__a, coke_signature__b, coke_audit);
CREATE INDEX index_3 ON q_coke_ap_checks_delivery_st_v(coke_chq_number_deliver);
I called the index_1,2,3 for easy to read obviously not a good naming convention.
With this in place your select should be optimized to retrieve you your data in an acceptable performance. But of course it all depends on the size and the distribution of your data which is hard to control without performing specific data analysis.
looking to you code .. seems you have redundant where condition the second NOT IN implies the firts so you could avoid
you could also transform you NOT IN clause in a MINUS clause .. join the same query with INNER join of you not in subquery
and last be careful you have proper composite index on table
Q_COKE_AP_CHECKS_SIGN_STATUS_V
cols (plan_id,COKE_SIGNATURE__A , COKE_SIGNATURE__B, COKE_AUDIT, COKE_CHQ_NUMBER, COKE_PAY_SUPPLIER)
SELECT DISTINCT
COKE_CHQ_NUMBER,
COKE_PAY_SUPPLIER
FROM
apps.Q_COKE_AP_CHECKS_SIGN_STATUS_V
WHERE
plan_id = 40192
AND COKE_SIGNATURE__A = 'YES'
AND COKE_SIGNATURE__B = 'YES'
AND COKE_AUDIT = 'YES'
MINUS
SELECT DISTINCT
COKE_CHQ_NUMBER,
COKE_PAY_SUPPLIER
FROM apps.Q_COKE_AP_CHECKS_SIGN_STATUS_V
INNER JOIN (
SELECT COKE_CHQ_NUMBER_DELIVER
FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V
) T ON T.COKE_CHQ_NUMBER_DELIVER = apps.Q_COKE_AP_CHECKS_SIGN_STATUS_V
WHERE
plan_id = 40192
AND COKE_SIGNATURE__A = 'YES'
AND COKE_SIGNATURE__B = 'YES'
AND COKE_AUDIT = 'YES'

Update column within CASE statement with results of a subquery postgres

I need to update a column based on the results of a subquery. If the subquery returns results for that column then the columns must be updated, is the query returns no results for that column then I need to update with 0.
I do not know where to place the subquery and how to combine it with the CASE statement. This is what I thought but the syntax is not correct. Can anybody help please?
(SELECT datazones.ogc_fid, count(*) as total
FROM suppliersnew suppliers, datazone_report_resupply datazones
WHERE St_contains(datazones.geom, suppliers.geometry) AND (suppliers.status = 'Under construction' OR
suppliers.status = 'Unknown' OR suppliers.status = 'Operational') GROUP by datazones.ogc_fid ORDER BY total ASC) sources
UPDATE datazone_report_resupply
SET es_actual =
CASE
WHEN datazone_report_resupply.ogc_fid = sources.ogc_fid THEN sources.total
ELSE 0
END
The query is a little hard to follow, because the aggregation is on the outer column (this is unusual). However, you don't need aggregation or order by. You only seem to care whether a row exists.
I think the logic is:
UPDATE datazone_report_resupply r
SET es_actual =
(CASE WHEN EXISTS (SELECT 1
FROM suppliersnew s
WHERE St_contains(r.geom, s.geometry) AND
s.status IN ('Under construction', 'Unknown', 'Operational')
)
THEN 1 ELSE 0
END);

SQL Server Update via Select Statement

I have the following sql statement and I want to update a field on the rows returned from the select statement. Is this possible with my select? The things I have tried are not giving me the desired results:
SELECT
Flows_Flows.FlowID,
Flows_Flows.Active,
Flows_Flows.BeatID,
Flows_Flows.FlowTitle,
Flows_Flows.FlowFileName,
Flows_Flows.FlowFilePath,
Flows_Users.UserName,
Flows_Users.DisplayName,
Flows_Users.ImageName,
Flows_Flows.Created,
SUM(CASE WHEN [Like] = 1 THEN 1 ELSE 0 END) AS Likes,
SUM(CASE WHEN [Dislike] = 1 THEN 1 ELSE 0 END) AS Dislikes
FROM Flows_Flows
INNER JOIN Flows_Users ON Flows_Users.UserID = Flows_Flows.UserID
LEFT JOIN Flows_Flows_Likes_Dislikes ON
Flows_Flows.FlowID=Flows_Flows_Likes_Dislikes.FlowID
WHERE Flows_Flows.Active = '1' AND Flows_Flows.Created < DATEADD(day, -60, GETDATE())
Group By Flows_Flows.FlowID, Flows_Flows.Active, Flows_Flows.BeatID,
Flows_Flows.FlowTitle, Flows_Flows.FlowFileName, Flows_Flows.FlowFilePath,
Flows_Users.UserName, Flows_Users.DisplayName, Flows_Users.ImageName,
Flows_Flows.Created
Having SUM(CASE WHEN [Like] = 1 THEN 1 ELSE 0 END) = '0' AND SUM(CASE WHEN [Dislike] = 1
THEN 1 ELSE 0 END) >= '0'
This select statement returns exactly what I need but I want to change the Active field from 1 to 0.
yes - the general structure might be like this: (note you don't declare your primary key)
UPDATE mytable
set myCol = 1
where myPrimaryKey in (
select myPrimaryKey from mytable where interesting bits happen here )
Because you haven't made your question more clear in what result you want to achieve, I'll provide an answer with my own assumptions.
Assumption
You have a select statement that gives you stuffs, and it works as desired. What you want it to do is to make it return results and update those selected rows on the fly - basically like saying "find X, tell me about X and make it Y".
Anwser
If my assumption is correct, unfortunately I don't think there is any way you can do that. A select does not alter the table, it can only fetch information. Similarly, an update does not provide more detail than the number of rows updated.
But don't give up yet, depending on the result you want to achieve, you have alternatives.
Alternatives
If you just want to update the rows that you have selected, you can
simply write an UPDATE statement to do that, and #Randy has provided
a good example of how it will be written.
If you want to reduce calls to server, meaning you want to make just
one call to the server and get result, as well as to update the
rows, you can write store procedures to do that.
Store procedures are like functions you wrote in programming languages. It essentially defines a set of sql operations and gives them a name. Each time you call that store procedure, the set of operations gets executed with supplied inputs, if any.
So if you want to learn more about store procedures you can take a look at:
http://www.mysqltutorial.org/introduction-to-sql-stored-procedures.aspx
If I understand correctly you are looking for a syntax to be able to select the value of Active to be 0 if it is 1. The syntax for something like that is
SELECT
Active= CASE WHEN Active=1 THEN 0 ELSE Active END
FROM
<Tables>
WHERE
<JOIN Conditions>

If Logic in a SQL Statement

What I'm trying to do should be very simple but somehow I can't reach the right answer to my problem.
I've asked something similar in the past but the answer given to me previously no longer fits the requirements.
So here's what's going on - I need to conditionally select values from a table in my database in a different than the usual manner, like so:
Table:
Id int (not null)
ParentId int (not null)
EventOn DateTime (not null)
User int (null)
By the following select:
SELECT RST.* FROM RangeSheetTime RST
WHERE RST.[User] is not null
(in the above case, I take all the rows where the user isn't null)
Select RST.* FROM RangeSheetTime RST
WHERE RST.[User] is null
(in the above case, I take all the rows where the user is null)
So what am I trying to do? I want to build a select statement that when given a condition, such as EventOn < GETDATE(), will retrieve all the rows where the USER isn't null. In case there aren't any rows where USER isn't null, then it should retrieve the rows where it is null, if any.
How can I put this to work?
Note: I can't use if here, otherwise this would be easier.
EDIT:
I'm going to try to explain it the best I can. Imagine I have 3 rows for the same ParentId, 31.
2 of these rows have a column named StartOrEnd set to 1. There's just a difference between them,
for the 1st one, the USER column is null; for the 2nd one, the USER column has the value 90.
The 3rd row has the column StartOrEnd set to 0.
Now, I want to display results no matter the value of startorend. But there's a catch.
For every startorend, if there are more than 1 row and one of them has USER set to null and the others not null,
then only the non null rows for that startorend will display. but in case there are no non null rows for this condition, than the null values will display. I hope I was clear now.
You should look into the CASE...WHEN construct, which is the equivalent of IF...THEN in SQL:
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5078041.html
This may work:
SELECT RST.* FROM RangeSheetTime RST
WHERE RST.[User] IS NOT NULL
UNION ALL
SELECT RST.* FROM RangeSheetTime RST
WHERE RST.[User] IS NULL
AND NOT EXISTS (
SELECT Id FROM RangeSheetTime
WHERE [User] IS NOT NULL
)
I have no means of testing this at the moment, so no guarantees.
If using sqlserver, look at the case statement, it might do what you want.
select a,b,
case when c is not null then 'The not null condition'
else 'The null condition
end [C]
from
Table T
where
condition
If using oracle, I think you can use decode.
Cheers.
Hallaghan, Are you asking about retrieval criteria or manipulating/ display of SQL result, if you are asking about manipulating or display of result case would help you else Union looks good to me.
id , parentid User , StartOrEnd
1 , 31, null , 1
2 , 31, 90 , 1
3 , 31, null , 0
and you want to say now, if startorEnd has multiple value for one parent id, you only want to see the row where user is not null , else the row with null user will come.
if it is like this, the answer given by Jeff should work
The final solution to this problem wasn't any easy to get at but after mashing our heads against a wall, me and a team mate got it down. Although every post from this topic helped us, none could really obtain the values we wanted, there were always flaws, but we are very thankful for all the help provided, without it we'd hardly have reached the answer by now.
So the solution is as follows:
select
P.ParentId RangeSheet
,coalesce(max(P.[End]), max(P.Start)) EventOn
,case when isnull(max(P.[End]), 0) = 0 then 1 else 0 end StartOrEnd
from
(
select
RST.ParentId
,case RST.StartOrEnd when 1 then RST.EventOn else null end Start
,case RST.StartOrEnd when 0 then RST.EventOn else null end [End]
from
(
select
coalesce(MAN.ParentId, AUT.ParentId) ParentId
,coalesce(MAN.StartOrEnd, AUT.StartOrEnd) StartOrEnd
,coalesce(max(MAN.CreatedOn), max(AUT.CreatedOn)) CreatedOn
from
(
-- Obter os manuais
select
RST.ParentId
,RST.StartOrEnd
,MAX(RST.CreatedOn) CreatedOn
from RangeSheetTime RST
where RST.[User] is not null
group by RST.ParentId, RST.StartOrEnd
) MAN
full outer join
(
-- Obter os automáticos
select
RST.ParentId
,RST.StartOrEnd
,MAX(RST.CreatedOn) CreatedOn
from RangeSheetTime RST
where RST.[User] is null
group by RST.ParentId, RST.StartOrEnd
) AUT on MAN.ParentId=AUT.ParentId and MAN.StartOrEnd=AUT.StartOrEnd
group by coalesce(MAN.ParentId, AUT.ParentId), coalesce(MAN.StartOrEnd, AUT.StartOrEnd)
) FOJ
inner join RangeSheetTime RST on FOJ.ParentId=RST.ParentId and FOJ.StartOrEnd=RST.StartOrEnd and FOJ.CreatedOn=RST.CreatedOn
) P
group by P.ParentId