I need to modify query for adding a filter - sql

Please help, I need to add a filter - from and to date. On the column tran_log.Tran_Date in the query given below. Please help me with the updated query.
SELECT
tran_log.FROM_CRN,
ktk_log.DEBIT_ACCT_NO,
ktk_log.TXN_AMOUNT,
ktk_log.EXT_SYSTEM || '-' || ktk_log.REFRENCE_NO AS "Kotak bank ref
number",
case when ktk_log.RETURN_CODE_STATUS = 0 then 'SUC' ELSE 'FAIL' END AS
"Status",
ktk_log.DEBIT_CREDIT_FLAG As "Transaction code",
ktk_log.ERROR_CODE,
KTK_LOG.APP_TYPE as "Merchant code",
tran_log.Tran_Date "Transaction_Date",
tran_log.SOURCE_REF_NO As "Merchant reference number"
FROM
KTK_TRANSACTION_LOG ktk_log
INNER JOIN transaction_log tran_log on TRAN_LOG.TRAN_REF_NO =
KTK_LOG.EXT_SYSTEM || '-' || KTK_LOG.REFRENCE_NO;

I THINK THIS COULD BE HELPFUL
SELECT * FROM TABLE
WHERE tran_log BETWEEN FRMDATE AND TODATE;

What is your actual question?
How to filter query results? Use a WHERE clause.
Whether to put the condition in a WHERE clause or extend your ON clause? Just decide. Both methods are equally okay. Extending the ON clause would have the advantage that you could change the inner join to an outer join more easily, if you ever want to do that.
How to use date literals? That's DATE 'yyyy-mm-dd', e.g. DATE '2019-06-20'.
How to compare dates? In Oracle there is no difference betwen a date and a datetime. The DATE datatype allows for a time with the date. So it is often preferred to use >= and < when checking against a date range. E.g. for April: where mydate >= date '2019-04-01' and mydate < '2019-05-01'. Thus you get everything from the first till the last nanosecond :-)

Related

Hive query to return single row based on eff and exp date

I have a table with the following data.
I am expecting row which needs to be returned is with exp_dt "2020-09-22". But when run below query it returning both the rows. I am not understanding why it is returning the first row also when it has eff_dt "2020-09-19".
select id,cd,eff_dt,exp_dt,post_dt from table
where from_unixtime(unix_timestamp(eff_dt,"yyyy-MM-dd")) <= from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
and from_unixtime(unix_timestamp(exp_dt,"yyyy-MM-dd")) >= from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"));
Is there any issue with my query? I am expecting 2nd row to be returned.
Use < for the comparison to exp_date:
select id,cd,eff_dt,exp_dt,post_dt
from table
where from_unixtime(unix_timestamp('2020-09-21', 'yyyy-MM-dd')) >= from_unixtime(unix_timestamp(eff_dt, 'yyyy-MM-dd')) and
from_unixtime(unix_timestamp('2020-09-22', 'yyyy-MM-dd')) < from_unixtime(unix_timestamp(exp_dt, 'yyyy-MM-dd'))
I reversed the comparison order. I find it easier to follow the logic with the constants first.
Does this capture the edge case of equal same day expiry and solve your problem at the same time?
select id,cd,eff_dt,exp_dt,post_dt from table
where
(from_unixtime(unix_timestamp(eff_dt,"yyyy-MM-dd")) <= from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
and
from_unixtime(unix_timestamp(exp_dt,"yyyy-MM-dd")) > from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
)
or
(from_unixtime(unix_timestamp(eff_dt,"yyyy-MM-dd")) = from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
and
from_unixtime(unix_timestamp(exp_dt,"yyyy-MM-dd")) = from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
)
;
In fact I suspect exp is always >= eff, so maybe only one condition
from_unixtime(unix_timestamp(eff_dt,"yyyy-MM-dd")) <= from_unixtime(unix_timestamp("2020-09-21","yyyy-MM-dd"))
is enough...?
You do not need from_unixtime(unix_timestamp()) because dates are already in correct format and argument is in the same yyyy-MM-dd format.
The issue in your query is that you are using equal for both eff and exp dates
To find latest record on date use this query:
select id,cd,eff_dt,exp_dt,post_dt from table
where eff_dt <= "2020-09-21"
and exp_dt > "2020-09-21";
There should be no records when eff_dt = exp_dt in SCD2 if you have only date (without time component). dates can be equal only if you are using timestamps, and time is different, in this case convert your argument date to timestamp before checking.
SCD2 should be designed in such way that fact record can be mapped to exactly one record of SCD2.

Fetching records from SQL based on Month name

So this my table structure and data.
Now I want to filter data based on Month by ExpenseDate column.
So how can I achieve that?
I was trying
select * from tblExpenses where (ExpenseDate = MONTH('April'))
But it throws an error: "Conversion failed when converting date and/or time from character string."
Please help. Thank you.
You are putting month() on the wrong column. It can be applied to ExpensesDate:
select *
from tblExpenses
where month(ExpenseDate) = 4;
Note that month() returns a number, not the name of the month.
I think it is more likely that you want records from a particular April, not every April. This would be expressed as:
where ExpenseDate >= '2018-04-01' and ExpenseDate < '2018-05-01'
I think your where clause is just reversed I think you want this (and change the word to a number)
select * from tblExpenses where Month(ExpenseDate) = 4

SQL left join with grouped table

received some great help on a previous question on this site.
Im new to sql and trying to get my head around this.
From table Tourenstatistik I will get unique rows of data with a date & id.
I am then looking at another table Vtsbreak and summing up the duration for each id on separate dates as there can be more than one entry for the same id on the same date.
I then want to return that sum in a column called duration for the unique id & its date.
I also need to specify the start and finish dates for my query.
I have found something similar but I cant get it to work
coming up with error ORA-00933: SQL command not properly ended.
Any suggestions please?
Select
Tourenstatistik.DATUM "Date",
Tourenstatistik.MITARBEITER "ID",
VtsPause.Duration
From
Tourenstatistik
Where Tourenstatistik.DATUM >= TO_DATE('2017/05/15', 'yyyy/mm/dd') AND Tourenstatistik.DATUM <= TO_DATE('2017/05/16','yyyy/mm/dd')
Left Join
(Select
Vtsbreak.MITARBEITER_NR "ID",
sum(Vtsbreak.DAUER) "Duration",
Vtsbreak.datum "Date"
From
Vtsbreak
Where DATUM >= TO_DATE('2017/04/01', 'yyyy/mm/dd') AND DATUM <= TO_DATE('2017/05/27','yyyy/mm/dd')
group by MITARBEITER_NR, datum;) as VtsPause
On (Tourenstatistik.MITARBEITER = VtsPause.MITARBEITER_NR and Tourenstatistik.DATUM = VtsPause.DATUM)
order by Tourenstatistik.DATUM, Tourenstatistik.MITARBEITER
You are giving the columns aliases in the subquery. You then need to use those aliases. Also, the WHERE clause is misplaced.
Select ts.DATUM as "Date", ts.MITARBEITER as "ID", b."Duration"
From Tourenstatistik ts Left Join
(Select b.MITARBEITER_NR, b.datum, sum(b.DAUER) as "Duration"
From Vtsbreak b
Where b.DATUM >= DATE '2017-04-01' AND
b.DATUM <= DATE '2017-05-27'
group by MITARBEITER_NR, datum
) b
On ts.MITARBEITER = b.MITARBEITER_NR and ts.DATUM = b.DATUM
Where ts.DATUM >= DATE '2017-05-15' and
ts.DATUM <= DATE '2017-05-16'
order by ts.DATUM, ts.MITARBEITER;
You have numerous things wrong with the query, plus a few suggestions:
You had a semicolon in the middle of the query.
You gave columns aliases in the subquery, and then used the original column names.
You had a misplaced WHERE clause.
Recommendations:
Use table abbreviations as table aliases, so the query is easier to write and to read.
Use the date keyword for defining date literals.
Try taking the "as" off of "as VtsPause". Also, get rid of the semicolon after "datum;". I'd also not give column aliases in double quotes on the inline query, especially since you refer to the actual column name in your ON clause.
Also, your first WHERE clause is out of place.
Perhaps this will work:
Select
Tourenstatistik.DATUM
Tourenstatistik.MITARBEITER,
VtsPause.Duration
From
Tourenstatistik
Left Join
(Select
Vtsbreak.MITARBEITER_NR,
sum(Vtsbreak.DAUER) duration,
Vtsbreak.datum
From
Vtsbreak
Where DATUM >= TO_DATE('2017/04/01', 'yyyy/mm/dd')
AND DATUM <= TO_DATE('2017/05/27','yyyy/mm/dd')
group by MITARBEITER_NR, datum) VtsPause
On (Tourenstatistik.MITARBEITER = VtsPause.MITARBEITER_NR
and Tourenstatistik.DATUM = VtsPause.DATUM)
Where Tourenstatistik.DATUM >= TO_DATE('2017/05/15', 'yyyy/mm/dd')
AND Tourenstatistik.DATUM <= TO_DATE('2017/05/16','yyyy/mm/dd')
order by Tourenstatistik.DATUM, Tourenstatistik.MITARBEITER

ORA-00907: missing right parenthesis using count with expression inside it

SELECT Hotel_Name, COUNT(H_CHECK.Hotel_checkIn >= 'JUL-1-2016' AND H_CHECK.Hotel_checkIn <= 'JUL-31-2016') FROM HOTEL, H_CHECK
GROUP BY Hotel_Name
ORA-00907: missing right parenthesis
I have tried putting Parenthesis in many ways, but I couldn't find the solution. I'm using Oracle Application Express 11G.
This is the query:
Display the hotel name that has more than 2 customers checked in on July 2016.
Once you fix your immediate syntax problem, you need proper JOIN syntax.
One way to fix the problem is simply to move the conditions to a WHERE clause, resulting in a query like this:
SELECT Hotel_Name, COUNT(hc.hotel_id)
FROM HOTEL h LEFT JOIN
H_CHECK hc
ON h.hotel_id = hc.hotel_id -- I don't know what the right join condition is
WHERE hc.Hotel_checkIn >= DATE '2016-07-01' AND
hc.Hotel_checkIn <= DATE '2016-07-31'
GROUP BY Hotel_Name;
You cannot count based on condition in Select statement of your sql query.
COUNT (
H_CHECK.Hotel_checkIn >= 'JUL-1-2016'
AND H_CHECK.Hotel_checkIn <= 'JUL-31-2016')
This is wrong. You can do it like>
SELECT Hotel_Name,
COUNT (1)
FROM HOTEL
join H_CHECK
ON H_CHECK.Hotel_checkIn >= 'JUL-1-2016'
AND H_CHECK.Hotel_checkIn <= 'JUL-31-2016'
GROUP BY Hotel_Name
having count(1) > 2;
You're missing the CASE ... END from your conditions inside your count. You're after something like:
SELECT Hotel_Name,
COUNT(case when H_CHECK.Hotel_checkIn >= 'JUL-1-2016'
AND H_CHECK.Hotel_checkIn <= 'JUL-31-2016'
then 1
end)
FROM HOTEL, H_CHECK
GROUP BY Hotel_Name;
However, there are a number of concerns I have regarding your query:
if your hotel_checkin column is of DATE datatype, then you should be comparing it to DATEs not strings. I.e. H_CHECK.Hotel_checkIn >= to_date('07-01-2016', 'mm-dd-yyyy') - this way, you avoid relying on implicit conversion of the string into a date, which relies on your NLS_DATE_FORMAT parameter setting. This could be changed and may cause your query to fail.
FROM HOTEL, H_CHECK Don't use the old-style method of joining; instead, use the ANSI style method: FROM hotel cross join h_check
Did you really mean the join to be a cross join or did you forget to add the join conditions?
You should alias the hotel_name column to aid maintainability.
You should also give your count column a name.
Since you're only counting rows with a checkin between 1st and 31st July 2016, you should move this condition into the where clause (as XING has shown in their answer) *unless* you need to also show hotels that don't have any checkins within that time period.
Your condition assumes that there are no time elements to the hotel_checkin column - ie. everything is set to midnight. If, however, you could have a date with a time, bear in mind that your count will ignore all rows with a checkin date of 31st July 2016 that are after midnight. In which case, your upper bound needs to change to: H_CHECK.Hotel_checkIn < to_date('08-01-2016', 'mm-dd-yyyy')

Access query won't work when dates have times

I have a query stated:
select *
from tblClient
where IntakeDate = #5/31/2011#
I know for a fact there are 8 records that have that date. But none of records with that date are pulled by this query. Those 8 records have times as well as "short date" (e.g. "5/31/2011 1:42:00 PM")
As a test I set the date to exactly 5/31/2011 for one record, and the query will work for that one record. Clearly the time value is interfering with this query.
I do not want to change all the date data to a strict 'short date' format and would like to work with it as-is. Can anyone give me some idea how I can make this work?
Create a condition that encompasses a single day's time range:
select *
from tblClient
where IntakeDate >= #5/31/2011# AND < #6/1/2011#
[You could use the DateValue() function on your column, but that would prevent any index being used.]
The DateValue function truncates the time off the date
select *
from tblClient
where DateValue(IntakeDate) = #5/31/2011#