Query always gives a result although it shouldn't - sql

I'd like to print the number of a room (stanza) only if that room has a reservation (prenotazione) between two dates in order to display an error message in php when the variable with the result is set. The problem is my query seems to check if any room has a reservation set between these dates and always gives output for any room asked.
SELECT stanze.num_stanza
FROM stanze, prenotazioni
WHERE prenotazioni.num_stanza=stanze.num_stanza
AND prenotazioni.check_in
BETWEEN '20190615'
AND '20190620'
OR prenotazioni.check_out
BETWEEN '20190615'
AND '20190620'
AND stanze.num_stanza='100'

Usually it is not good to have WHERE clauses like x OR y AND z. Try (x OR y) AND z. Otherwise if x is true then it will select no matter what z is.
e.g.
WHERE prenotazioni.num_stanza = stanze.num_stanza
AND (prenotazioni.check_in BETWEEN '20190615' AND '20190620' OR prenotazioni.check_out BETWEEN '20190615' AND '20190620')
AND stanze.num_stanza = '100'

It is not clear what you want exactly -- a full overlap or a partial overlap.
Either way, you can use EXISTS. The following is for a partial overlap:
SELECT s.num_stanza
FROM stanze s
WHERE EXISTS (SELECT 1
FROM prenotazioni p
WHERE p.num_stanza = s.num_stanza AND
p.check_in < '20190620' AND
p.check_out >= '20190615'
) AND
s.num_stanza = 100 -- looks like number so it probably is

Related

Postgresql: Update column from select and add condition when multiple rows returned

Basically, I need to update a column using a SELECT, which can return more than one value. If that happens, I'd like to apply a second condition to determine which of those values is to be chosen:
UPDATE train
SET var1 = (
CASE
WHEN (SELECT COUNT(*)
FROM cars
WHERE (train.var2 LIKE cars.var2))
> 1)
THEN (
SELECT var1
FROM cars
WHERE (train.var2 LIKE cars.var2)
AND cars.var2 in (
SELECT var2
FROM cars
WHERE train.user_id = cars.user_id)
)
ELSE (
SELECT var1
FROM cars
WHERE (train.var2 LIKE cars.var2))
)
END
);
I think the above works, but I repeat 3 times the same SELECT. Do you have a nice way to avoid that? Maybe there is a simple way to catch when the select returns more than one value and do something about it?
Thank you
update train set
var1 = (
select cars.var1
from cars
where train.var2 like cars.var2
order by train.user_id = cars.user_id desc
limit 1);
The above answer is good and works out of the box. If you do a lot of these, take a look at: https://wiki.postgresql.org/wiki/First/last_(aggregate)
Then you can do this:
update train set
var1 = (
select first(cars.var1 order by train.user_id = cars.user_id desc)
from cars
where train.var2 like cars.var2
);
Depending on your exact use-case this may be neater, easier to read, easier to reason about (order by in subselect is full of nasty edge-cases) or just more faff than it's worth.

Can't get all of the data I want out of a join

I have a hive table that has some http sessions that I need to analyze. One column has a http session ID that is consistent throughout the entire session.
I'm trying find all rows that are part of sessions where one of a certain set of actions was performed AND the session ended in a timeout.
set hive.cli.print.header=true;
SELECT * FROM
(SELECT DISTINCT id, x_date, y
FROM log
WHERE ((to_date(x_date)) >= (date_sub(current_date, 1)))
AND y like '%timeout%') u
JOIN
(SELECT id, x_date, y, z, q, a
FROM log
WHERE ((to_date(x_date)) >= (date_sub(current_date, 1)))
AND z in ('1', '2', '3', '4')) o
ON u.id = o.id
ORDER BY u.id, o.x_date;
What I'm trying to find is all rows where
id = 123 and y like '%timeout%'
AND (id = 123 and z in('1','2','3','4')
What I am currently getting is something like
if (id = 123 and y like %timeout%)
select * where (id = 123 and z in ('1','2','3','4'))
The expected output should be much larger than the actual output, as I should get many lines that only has ID = 123.
The problem is I need this for all IDs that meet both criteria, so I have to actually find all of the IDs first :)
I hope this makes sense, I feel like I may have worded the question in a confusing manner.
Try this it would work in SQL, I'm not super versed in Hive, but it should work based on what I've read.
SELECT id, x_date, y, z, q, a
FROM log
WHERE z IN ('1','2','3','4','5')
AND id IN (
SELECT id
FROM log
WHERE ((to_date(x_date)) >= (date_sub(current_date, 1)))
AND y like '%timeout%')

SAP Query IMRG Measure documents

I'm learning SAP queries.
I want to get all the Measure documents from an equipement.
To do that, I use 3 tables :
EQUI, IMPTT, IMRG
The query works but I have all documents instead I only want to get the last one by Date. But I can't do that. I'm sure that I have to add a custom field, but I have tried but none of them works.
For example, my last code :
select min( IMRG~INVTS ) IMRG~RECDV
from IMRG inner join IMPTT on
IMRG~POINT = IMPTT~POINT into (INVTS, IMRGVAL)
where IMRG~POINT = IMPTT-POINT AND
IMPTT~MPOBJ = EQUI-OBJNR
and IMRG~CANCL = '' group by IMRG~MDOCM IMRG~RECDV.
ENDSELECT.
Thanks for your help.
You will need to get the date from IMRG, and the inverted timestamp field, so the MIN() of this will be the most recent - that looks correct.
However your GROUP BY looks wrong. You should be grouping on the IMPTT~POINT field so that you get one record per measurement point. Note that one Point IMPTT can have many measurements (IMRG), so something like this:
SELECT EQUI-OBJNR, IMPTT~POINT, MIN(IMRG~IMRC_INVTS)
...
GROUP BY EQUI-OBJNR, IMPTT~POINT
If I got you correctly, you are trying to get the freshest measurement of the equipment disregard of measurement point. So you can try this query, which is not so beautiful, but it just works.
SELECT objnr COUNT(*) MIN( invts )
FROM equi AS eq
JOIN imptt AS tt
ON tt~mpobj = eq~objnr
JOIN imrg AS ig
ON ig~point = tt~point
INTO (wa_objnr, count, wa_invts)
WHERE ig~cancl = ''
GROUP BY objnr.
SELECT SINGLE recdv FROM imrg JOIN imptt ON imptt~point = imrg~point INTO wa_imrgval WHERE invts = wa_invts AND imptt~mpobj = wa_objnr.
WRITE: / wa_objnr, count, wa_invts, wa_imrgval.
ENDSELECT.

when 2 output values are returned it should display the hardcorded one and if 1 output value is returned it should display the 1output itself

When I execute a query for input parameter ABC it returns two values (Partner, Smith); whenever two values are returned of those two values Smith will be a compulsory value which will be returned.
But whenever the same query is executed with input parameter as 'xyz' it returns only one value.
Now my requirement is whenever I execute a query if it returns two values of those two values only SMITH must be returned in output and if the same query returns one output value then it should display the loutput value itself.
The below query satisfies 1st part of my requirement but it doesn’t satisfy my 2nd part of the requirement. Instead of displaying the 1output value it’s returning ‘Null’ value whenever the output value quantity is 1.
SELECT R.REGION_GID
FROM GTM_TRANSACTION T,
GTM_TRANSACTION_INVOLVED_PARTY P,
CONTACT C,
LOCATION L,
REGION_DETAIL R
WHERE T.GTM_TRANSACTION_GID=P.GTM_TRANSACTION_GID
AND R.COUNTRY_CODE3_GID = L.COUNTRY_CODE3_GID
AND R.REGION_GID LIKE 'SSN/BP.GTM_COMPL%'
AND L.LOCATION_GID = C.LOCATION_GID
AND P.INVOLVED_PARTY_CONTACT_GID=C.CONTACT_GID
AND P.INVOLVED_PARTY_QUAL_GID='SHIP_FROM'
AND T.GTM_TRANSACTION_GID=$SHIP_FORM
INTERSECT
SELECT R.REGION_GID
FROM GTM_TRANSACTION T,
GTM_TRANSACTION_INVOLVED_PARTY P,
CONTACT C,
LOCATION L,
REGION_DETAIL R
WHERE T.GTM_TRANSACTION_GID=P.GTM_TRANSACTION_GID
AND R.COUNTRY_CODE3_GID = L.COUNTRY_CODE3_GID
AND R.REGION_GID ='SSN/BP.GTM_COMPL_NO_CODING'
AND L.LOCATION_GID = C.LOCATION_GID
AND P.INVOLVED_PARTY_CONTACT_GID=C.CONTACT_GID
AND P.INVOLVED_PARTY_QUAL_GID='SHIP_FROM'
AND T.GTM_TRANSACTION_GID=$SHIP_FROM
As far as I can tell, the only difference between the two halves of your INTERSECT are in the filters for P.REGION_GID. The first half has:
R.REGION_GID LIKE 'SSN/BP.GTM_COMPL%'
while the second has
R.REGION_GID = 'SSN/BP.GTM_COMPL_NO_CODING'
Given how INTERSECT works, I think this means the first half is redundant. The only question then is whether the second half is returning one row or two rows. You want it to always return one row, with 'SMITH' taking precedence. The following logic may be what you want (as a bonus, I've tidied up your JOINs too):
SELECT TOP 1
R.REGION_GID
FROM
GTM_TRANSACTION T
JOIN GTM_TRANSACTION_INVOLVED_PARTY P ON
T.GTM_TRANSACTION_GID=P.GTM_TRANSACTION_GID
JOIN CONTACT C ON
P.INVOLVED_PARTY_CONTACT_GID=C.CONTACT_GID
JOIN LOCATION L ON
L.LOCATION_GID = C.LOCATION_GID
JOIN REGION_DETAIL R ON
R.COUNTRY_CODE3_GID = L.COUNTRY_CODE3_GID
WHERE
R.REGION_GID ='SSN/BP.GTM_COMPL_NO_CODING'
AND P.INVOLVED_PARTY_QUAL_GID='SHIP_FROM'
AND T.GTM_TRANSACTION_GID=$SHIP_FROM
ORDER BY
CASE WHEN R.REGION_GID = 'SMITH' then 1 else 2 end
That last line will want to be something like: CASE WHEN R.REGION_GID = 'SMITH' then 1 else 2 end but I you haven't told us much about your data, so I really don't know.

How to do multiple join / group by selects using sqlite3?

I have a sqlite3 database with one table called orig:
CREATE TABLE orig (sdate date, stime integer, orbnum integer);
What I want to do is select the first date/time for each orbnum. The only problem is that stime holds the time as a very awkward integer.
Assuming a six-digit number, the first two digits show the hour, the 3./4. show the minutes, and the last two digits show the seconds. So a value of 12345 is 1:23:45, whereas a value of 123456 is 12:34:56.
I figured I'd do this using two nested join/group statements, but somehow I cannot get it to work properly. Here's what I've got so far:
select s.orbnum, s.sdate, s.stime
from (
select t.orbnum, t.sdate, t.stime, min(t.sdate) as minsdate
from (
select orbnum, sdate, stime, min(stime) as minstime
from scia group by orbnum, sdate
) as t inner join orig as s on s.stime = t.minstime and s.sdate = t.sdate and s.orbnum = t.orbnum
) as d inner join scia as s on s.stime = d.stime and s.sdate = minsdate and s.orbnum = d.orbnum
where s.sdate >= '2002-08-01' limit 0,200;
This is the error I get:
Error: no such column: t.orbnum
I'm sure it's just some stupid mistake, but actually, I'm quite new to SQL ...
Any help is greatly appreciated :)
Edit:
After fixing the obvious typo, the query runs -- but returns an empty result set. However, the table holds ~10yrs of data, with about 12 orbnums per day and about 4-5 different times per orbnum. So I guess there's some mistake in the logic of the query ...
In your last join, you have d, which is the result of your double nested select, and you join s on it. From there, t is not visible. That’s why you get the “no such column: t.orbnum” error. Maybe you meant s.orbnum = d.orbnum?