oracle date function to append month and year - sql

Hi have query like this now i want to append value in query so tran_date is in Date time format in databases: so consider these two query
query 1:: i have to append value in date format but it not working ..how to pass year and month in date type::
select TRAN_DATE,
trunc(nvl(SUM(SALES_VALUE), 0) + nvl(sum(total_sales), 0) -
nvl(sum(net_sales), 0) + nvl(sum(discount), 0)) Sale
from OUTLET_PAYMODE_REPORT_FACT A, OUTLET_DETAILS B
WHERE A.OUTLET_ID = B.OUTLET_ID
and SALES_VALUE > 0
and to_date(TRAN_DATE, 'yyyy') = '2013'
AND to_date(TRAN_DATE, 'MON') = 'APR'
OR to_date(TRAN_DATE, 'yyyy') = '2013'
AND to_date(TRAN_DATE, 'MON') = 'MAR'
GROUP BY TRAN_DATE
query 2: its work but it is string format
select TRAN_DATE,
trunc(nvl(SUM(SALES_VALUE), 0) + nvl(sum(total_sales), 0) -
nvl(sum(net_sales), 0) + nvl(sum(discount), 0)) Sale
from OUTLET_PAYMODE_REPORT_FACT A, OUTLET_DETAILS B
WHERE A.OUTLET_ID = B.OUTLET_ID
and SALES_VALUE > 0
and (to_char(TRAN_DATE, 'yyyy') = '2013' AND
to_char(TRAN_DATE, 'MON') = 'APR')
OR (to_char(TRAN_DATE, 'yyyy') = '2013' AND
to_char(TRAN_DATE, 'MON') = 'MAR')
GROUP BY TRAN_DATE

One of options is to use BETWEEN condition with DATETIME datatype columns:
select TRAN_DATE,
trunc(nvl(SUM(SALES_VALUE), 0) + nvl(sum(total_sales), 0) -
nvl(sum(net_sales), 0) + nvl(sum(discount), 0)) Sale
from OUTLET_PAYMODE_REPORT_FACT A, OUTLET_DETAILS B
WHERE A.OUTLET_ID = B.OUTLET_ID
and SALES_VALUE > 0
and TRAN_DATE between to_date('01.03.2013', 'dd.mm.yyyy') and
to_date('30.04.2013', 'dd.mm.yyyy')
GROUP BY TRAN_DATE;

Related

How to insert a dynamic where clause within a case when in ATHENA

i have this query
SELECT case
when {{aggtime}} = 'HOURLY' then parsedatetime(formatdatetime("PUBLIC"."ORDERS"."CREATED_AT", 'yyyyMMddHH'), 'yyyyMMddHH')
when {{aggtime}} = 'DAILY' then CAST("PUBLIC"."ORDERS"."CREATED_AT" AS date)
when {{aggtime}} = 'WEEKLY' then dateadd('day', CAST((1 - CASE WHEN ((iso_day_of_week("PUBLIC"."ORDERS"."CREATED_AT") + 1) % 7) = 0 THEN 7 ELSE ((iso_day_of_week("PUBLIC"."ORDERS"."CREATED_AT") + 1) % 7) END) AS long), CAST("PUBLIC"."ORDERS"."CREATED_AT" AS date))
when {{aggtime}} = 'MONTHLY' then parsedatetime(formatdatetime("PUBLIC"."ORDERS"."CREATED_AT", 'yyyyMM'), 'yyyyMM')
when {{aggtime}} = 'YEARLY' then parsedatetime(formatdatetime("PUBLIC"."ORDERS"."CREATED_AT", 'yyyy'), 'yyyy')
END
AS "CREATED_AT", sum("PUBLIC"."ORDERS"."QUANTITY") AS "sum"
FROM "PUBLIC"."ORDERS"
WHERE year(CREATED_AT)=2020 and month(CREATED_AT) = 1 and day(CREATED_AT) = 01
GROUP BY "CREATED_AT"
i need the where clause only when {{aggtime}}='HOURLY', otherwise i need only the year
How can i achieve it ?
ps :. {{aggtime}} is a parameter for Metabase

How to Add one row to another

I have a set of data which is shown in picture:
I've tried adding January to February using the lead function which was correct shown in the picture below again:
And I thought it will add and add to the next row like a for loop but it did not.
I am asking for help on how to add the data again and again like a for loop would do. I've pasted the code I used below.
;WITH MonthActiveUsers AS (
SELECT MonthLogin, COUNT(MonthLogin) AS ActiveUsers
FROM #TEMPDistinctActiveUsersPerMonth DAUPM
GROUP BY MonthLogin
)
SELECT MAU.MonthLogin, (LEAD(MAU.ActiveUsers,0) OVER (ORDER BY MAU.MonthLogin ASC) + LEAD(MAU.ActiveUsers,1) OVER (ORDER BY MAU.MonthLogin ASC)) AS [Count of Active Users]
FROM
( SELECT CASE
WHEN MonthLogin = 'January'
THEN '2020-01-01'
WHEN MonthLogin = 'February'
THEN '2020-02-01'
WHEN MonthLogin = 'March'
THEN '2020-03-01'
WHEN MonthLogin = 'April'
THEN '2020-04-01'
WHEN MonthLogin = 'May'
THEN '2020-05-01'
WHEN MonthLogin = 'June'
THEN '2020-06-01'
ELSE NULL
END AS [MonthLogin]
,ActiveUsers
FROM MonthActiveUsers MAU
) MAU
The desired result would be:
January = 3313
February = 3349
March = 3398
April = 3421
May = 3437
June = 3444
I think that you want a window sum:
WITH ...
SELECT
MAU.MonthLogin,
SUM(MAU.ActiveUsers) OVER (ORDER BY MAU.MonthLogin) [Count of Active Users]
FROM ...
Note that the query can be simplified a little by using the short-circuit form of CASE, and mixing aggregation and window functions:
SELECT
MonthLogin,
COUNT(*) ActiveUsers,
SUM(COUNT(*)) OVER(ORDER BY MonthLogin) [Count of Active Users]
FROM (
SELECT
CASE MonthLogin
WHEN'January' THEN '2020-01-01'
WHEN'February' THEN '2020-02-01'
WHEN'March' THEN '2020-03-01'
WHEN'April' THEN '2020-04-01'
WHEN'May' THEN '2020-05-01'
WHEN'June' THEN '2020-06-01'
END AS MonthLogin
FROM #TEMPDistinctActiveUsersPerMonth
) t
GROUP BY MonthLogin
ORDER BY MonthLogin

Case Expression and dates

I have the below case expression.
SELECT end_dt,
CASE WHEN TO_CHAR(A.END_DT,'MM/DD/YYYY') = '01/01/3000' THEN ''
WHEN TO_CHAR(A.END_DT,'MM/DD/YYYY') > TO_CHAR(SYSDATE,'MM/DD/YYYY') THEN TO_CHAR(SYSDATE,'MM/DD/YYYY')
ELSE TO_CHAR(A.END_DT,'MM/DD/YYYY')
END ENDDATE,
CASE WHEN TO_CHAR(A.END_DT,'YYYYMM') = '300001' THEN ''
WHEN TO_CHAR(A.END_DT,'YYYYMM') > TO_CHAR(SYSDATE,'YYYYMM') THEN TO_CHAR(SYSDATE,'YYYYMM')
ELSE TO_CHAR(A.END_DT,'YYYYMM')
END ENDDATE_YYYYMM,
CASE WHEN TO_CHAR(A.END_DT,'YYYY') = '3000' THEN ''
WHEN TO_CHAR(A.END_DT,'YYYY') > TO_CHAR(SYSDATE,'YYYY') THEN TO_CHAR(SYSDATE,'YYYY')
WHEN TO_CHAR(A.END_DT,'YYYY') > TO_CHAR(SYSDATE,'YYYY') THEN TO_CHAR(SYSDATE,'YYYY')
ELSE TO_CHAR(A.END_DT,'YYYY')
END ENDDATE_YYYY
FROM A
LEFT D ON A.ID = D.ID
WHERE 1=1
ORDER BY 1
OutPut:
End_dt ENDDATE ENDDATE_YYYYMM ENDDATE_YYYY
12/5/2012 14:33:24 01/05/2018 201212 2012
Expected output:
End_dt ENDDATE ENDDATE_YYYYMM ENDDATE_YYYY
12/5/2012 14:33:24 12/5/2012 201212 2012
Why do I get a result of 01/05/2018 and not 12/5/2012?
You're doing string comparisons on dates. Stop. Do date comparisons on dates.
The string '12/5/2012' is greater than the string '01/05/2018' because 1 is greater than 0. Oracle is performing a binary comparison.
SQL> select *
2 from dual
3 where '12/5/2012' > '01/05/2018';
D
-
X
Stop converting all your dates to strings and all will be well
SQL> select *
2 from dual
3 where date '2018-05-01' > date '2012-05-12';
D
-
X
Incidentally, the empty string '' is equivalent to NULL in Oracle.
Your query should look like:
CASE WHEN A.END_DT = date '3000-01-01' then null
WHEN A.END_DT > SYSDATE THEN TO_CHAR(SYSDATE,'MM/DD/YYYY')
ELSE TO_CHAR(A.END_DT,'MM/DD/YYYY')
END ENDDATE,
Don't do date comparisons as strings. It works for the other values, because you have the right format -- YYYYMMDD (or a partial piece of that).
Try this logic:
SELECT end_dt,
(CASE WHEN TO_CHAR(A.END_DT, 'MM/DD/YYYY') = '01/01/3000' THEN ''
WHEN A.END_DT > SYSDATE
THEN TO_CHAR(SYSDATE, 'MM/DD/YYYY')
ELSE TO_CHAR(A.END_DT, 'MM/DD/YYYY')
END) as ENDDATE,
(CASE WHEN TO_CHAR(A.END_DT, 'YYYYMM') = '300001' THEN ''
WHEN TO_CHAR(A.END_DT, 'YYYYMM') > TO_CHAR(SYSDATE, 'YYYYMM')
THEN TO_CHAR(SYSDATE,'YYYYMM')
ELSE TO_CHAR(A.END_DT,'YYYYMM')
END) as ENDDATE_YYYYMM,
(CASE WHEN TO_CHAR(A.END_DT, 'YYYY') = '3000' THEN ''
WHEN TO_CHAR(A.END_DT, 'YYYY') > TO_CHAR(SYSDATE, 'YYYY')
THEN TO_CHAR(SYSDATE, 'YYYY')
WHEN TO_CHAR(A.END_DT, 'YYYY') > TO_CHAR(SYSDATE,'YYYY')
THEN TO_CHAR(SYSDATE, 'YYYY')
ELSE TO_CHAR(A.END_DT, 'YYYY')
END) as ENDDATE_YYYY

Select Case FROM Union

In a purpose of reporting and creating report (MS SQL SERVER 2014) which will compare number of transactions and amounts from last day, same day last week and same day last month I need some query like this one, which is not working:
Select
Acquirer = case when Date = #Day then a.Acquirer
when Date = #LastWeekDay then b.Acquirer
when Date = #LastMonthDay then c.Acquirer
end
, RC = case when Date = #Day then a.RC
when Date = #LastWeekDay then b.RC
when Date = #LastMonthDay then c.RC
end
, Desc = case when Date = #Day then a.Desc
when Date = #LastWeekDay then b.Desc
when Date = #LastMonthDay then c.Desc
end
, Day_Tr_Count = case when Date = #Day then a.Count end
, LWD_Tr_Count = case when Date = #LastWeekDay then b.Count end
, LMD_Tr_Count = case when Date = #LastMonthDay then c.Count end
, Day_Tr_Amount = case when Date = #Day then a.Amount end
, LWD_Tr_Amount = case when Date = #LastWeekDay then b.Amount end
, LMD_Tr_Amount = case when Date = #LastMonthDay then c.Amount end
from
( select * from T1
union
select * from T2
union
select * from T3) x
group by Acquirer,RC,Desc
All 3 tables have pretty same structure:
T1,T2,T3(acquirer,RC,Desc,Count,Amount,Date).
Report should be:
result_table(Acquirer,RC,Desc,Daily_Count,Last_Week_Day_Count,Last_Month_Count,Daily_Amount,Last_Week_Day_Amount,Last_Month_Day_Amount)
Hmmm. You have an aggregation query with no group by. Perhaps:
Select v.Acquirer, v.RC, v.Desc,
Day_Tr_Count = sum(case when Date = #Day then a.Count end),
LWD_Tr_Count = sum(case when Date = #LastWeekDay then b.Count end),
LMD_Tr_Count = sum(case when Date = #LastMonthDay then c.Count end),
Day_Tr_Amount = sum(case when Date = #Day then a.Amount end
LWD_Tr_Amount = sum(case when Date = #LastWeekDay then b.Amount end),
LMD_Tr_Amount = sum(case when Date = #LastMonthDay then c.Amount end)
from (select * from T1
union all
select * from T2
union all
select * from T3
) x cross apply
(values (case when Date = #Day then a.Acquirer
when Date = #LastWeekDay then b.Acquirer
when Date = #LastMonthDay then c.Acquirer
end,
case when Date = #Day then a.RC
when Date = #LastWeekDay then b.RC
when Date = #LastMonthDay then c.RC
end,
case when Date = #Day then a.Desc
when Date = #LastWeekDay then b.Desc
when Date = #LastMonthDay then c.Desc
end
) v (Acquirer, RC, Desc)
group by v.Acquirer, v.RC, v.Desc;
Note: desc is a bad name for a column (or anything else). It is a SQL keyword (think order by).

Rewrite SQL query to return rows for each dataset

I have the following table for student's fee payments
[fee_id] INT
[user_id] INT
[payment] DECIMAL (18, 2)
[date] DATETIME
[fee_remaining] DECIMAL (18, 2)
[year] INT
[payment_method] NVARCHAR (50)
[fee_required] DECIMAL (18, 2)
This is my current query to display the number of students who have either paid, yet to pay or have partially paid their fees for the year
SELECT DISTINCT
(SELECT COUNT(*) AS Expr1
FROM fee_payments
WHERE (fee_remaining = 0)
AND (YEAR = #year)) AS Fully_Paid,
(SELECT COUNT(*) AS Expr1
FROM fee_payments
WHERE (fee_remaining = fee_required)
AND (YEAR = #year)) AS Unpaid,
(SELECT COUNT(*) AS Expr1
FROM fee_payments
WHERE (fee_remaining > 0)
AND (YEAR = #year)
AND (fee_remaining <> fee_required)) AS Partially_Paid
FROM fee_payments AS fee_payments_1
This is my output
Fully_Paid | Unpaid | Partially_Paid
-------------------------------------
8 | 1 | 5
Is it at all possible to have my output displayed as follows?
Status | Total
----------------------------
Fully Paid | 8
Unpaid | 1
Partially Paid | 5
Any help would be greatly appreciated
Use a case expression to assign the required status to each row and group by the calculated column.
select status, count(*) as total
from (
SELECT
case when fee_remaining = 0 then 'fully_paid'
when fee_remaining <> fee_required then 'partially_paid'
when fee_remaining = fee_required then 'unpaid'
end as status
FROM fee_payments
WHERE YEAR = #year) t
group by status
Also note this assumes fee_remaining and fee_required are non null values. If they can be null, use coalesce to handle them when comparing.
So without completely restructuring your query into something more efficient like kvp's answer, you could UNION each of the results instead of using them each as a sub-query:
SELECT 'Fully Paid' AS Status, COUNT(*) AS Total
FROM fee_payments
WHERE (fee_remaining = 0) AND (YEAR = #year)
UNION
SELECT 'Unpaid', COUNT(*)
FROM fee_payments
WHERE (fee_remaining = fee_required) AND (YEAR = #year)
UNION
SELECT 'Partially Paid', COUNT(*)
FROM fee_payments
WHERE (fee_remaining > 0) AND (YEAR = #year) AND (fee_remaining <> fee_required)
Your code appears to have more than one row per year. It seems like the last row would be the most informative, so I'm thinking something like this:
select sum(case when fee_remaining = 0 then 1 else 0 end) as FullyPaid,
sum(case when fee_remaining < fee_required then 1 else 0 end) as PartiallyPaid,
sum(case when fee_remaining = fee_required then 1 else 0 end) as Unpaid
from (select fp.*,
row_number() over (partition by user_id order by date desc) as seqnum
from fee_payments fp
where YEAR = #year
) fp
where seqnum = 1;
SELECT 'Fully Paid' as Status, COUNT(*) AS Total
FROM fee_payments
GROUP BY year
WHERE fee_remaining = 0
AND YEAR = #year
UNION ALL
SELECT 'Unpaid' as Status, COUNT(*) AS Total
FROM fee_payments
GROUP BY year
WHERE fee_remaining = fee_required
AND YEAR = #year
UNION ALL
SELECT 'Partially Paid' as Status, COUNT(*) AS Total
FROM fee_payments
GROUP BY year
WHERE fee_remaining > 0
AND YEAR = #year
AND fee_remaining <> fee_required