How to convert thsis MYSQL query to Laravel sql query?
SELECT *
FROM (
SELECT
year(invoiceDate) as [year],left(datename(month,invoicedate),3)as [month],
InvoiceAmount as Amount
FROM Invoice
) as s
PIVOT
(
SUM(Amount)
FOR [month] IN (jan, feb, mar, apr,
may, jun, jul, aug, sep, oct, nov, dec)
)AS pivot
Please any one write this above code to Laravel DB Builder format using these any methods.
eg: $pivot=DB::table('Invoice')->where()...
and also, eg: $pivote=Invoice::where()->..
How to write code for pivot?
Here how you implement your code with DB:raw and DB::select
$results =
DB::select(
DB::raw("
SELECT *
FROM (
SELECT
year(invoiceDate) as [year],left(datename(month,invoicedate),3)as [month],
InvoiceAmount as Amount
FROM Invoice
) as s
PIVOT
(
SUM(Amount)
FOR [month] IN (jan, feb, mar, apr,
may, jun, jul, aug, sep, oct, nov, dec)
)AS pivot
")
);
Note: This is to show/demonstrate how to put sql statement inside DB::raw as per your request in the question, but this does not mean I have check your sql statement.
Related
I have 2 tables. First table TABLE1 has 3 columns (ROLLNO, CODE, ADM_DT).
CREATE TABLE TABLE1
( ROLLNO VARCHAR2(3) NOT NULL,
CODE VARCHAR2(3) NOT NULL,
ADM_DT TIMESTAMP(3) NOT NULL
);
Second table TABLE2 has 3 columns (CODE, YEAR).
CREATE TABLE TABLE2
(
CODE VARCHAR2(3) NOT NULL,
YEAR VARCHAR2(4) NOT NULL
);
TABLE1 has few records mentioned below:
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('100','ABC', '12-NOV-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('101','ACD', '12-DEC-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('102','ABD', '15-JAN-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('103','DEF', '14-AUG-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('104','DFE', '17-JUL-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('105','FED', '21-SEP-21 12.00.00.000000000 AM');
ROLLNO CODE ADM_DT
-----------------------------------
100 ABC 12-NOV-21 12.00.00.000000000 AM
101 ACD 12-DEC-21 12.00.00.000000000 AM
102 ABD 15-JAN-21 12.00.00.000000000 AM
103 DEF 14-AUG-21 12.00.00.000000000 AM
104 DFE 17-JUL-21 12.00.00.000000000 AM
105 FED 21-SEP-21 12.00.00.000000000 AM
TABLE2 has few records mentioned below:
INSERT INTO TABLE2(CODE, YEAR) VALUES ('ABC','2022');
INSERT INTO TABLE2(CODE, YEAR) VALUES ('ADC','2022');
INSERT INTO TABLE2(CODE, YEAR) VALUES ('DEF','2021');
INSERT INTO TABLE2(CODE, YEAR) VALUES ('DFE','2021');
CODE YEAR
-------------
ABC 2022
ADC 2022
DEF 2021
DFE 2021
I need to select the records from TABLE1 in such a way that
1) fetch the month present in ADM_DT value and if month is between Sep and Dec and also the year, then check the CODE value present in YEAR+1 of TABLE2, if present then don't select the record from TABLE1 else select.
Ex: Let us take a record of ROLLNO = '102' and CODE is 'ABC' and it has ADM_DT as '12-NOV-21 12.00.00.00.000000000 AM' so here month is November and the year is 2021, so check whether CODE 'ABC' present in TABLE2 with YEAR '2022'...code 'ABC' present in TABLE2, then don't select this record from TABLE1.
2) fetch the month present in ADM_DT value and if month is between Jan and Aug, then check the CODE value present in YEAR of TABLE2, if present then don't select the record from TABLE1 else select.
Ex: Let us take a record of ROLLNO = '103' and CODE is 'DEF' and it has ADM_DT as '14-AUG-21 12.00.00.00.000000000 AM' so here month is August and the year is 2021 so check whether CODE 'DEF' present in TABLE2 with YEAR '2021'...code 'DEF' present in TABLE2, then don't select this record from TABLE1.
This is the Result table I need:
ROLLNO CODE ADM_DT
------------------------------------------------
101 ACD 12-DEC-21 12.00.00.00.000000000 AM
102 ABD 15-JAN-21 12.00.00.00.000000000 AM
105 FED 21-SEP-21 12.00.00.00.000000000 AM
This is the Result table I am getting:
ROLLNO CODE ADM_DT
------------------------------------------------
100 ABC 12-NOV-21 12.00.00.000000000 AM (This shouldn't get picked up as this record has Month as Nov and year as 2021, so we need to go to the TABLE2 and check whether we have CODE 'ABC' in the YEAR '2022', its present so it shouldn't pick up)
101 ACD 12-DEC-21 12.00.00.000000000 AM
102 ABD 15-JAN-21 12.00.00.000000000 AM
105 FED 21-SEP-21 12.00.00.000000000 AM
This is the query I have tried:
SELECT * FROM TABLE1 T1
WHERE NOT EXISTS (
SELECT 1 FROM TABLE2 T2
WHERE T1.CODE = T2.CODE
AND EXTRACT(YEAR FROM T1.ADM_DT) =
CASE
WHEN EXTRACT(MONTH FROM(T1.ADM_DT)) BETWEEN 9 AND 12 THEN TO_NUMBER(T2.YEAR)+1
WHEN EXTRACT(MONTH FROM(T1.ADM_DT)) BETWEEN 1 AND 8 THEN TO_NUMBER(T2.YEAR)
END
);
Is this correct query? because I have executed this query and it gave me wrong result...might be issue with YEAR logic I have written in query (Need to use NOT EXISTS query).
You can create a range from the table2.year rather than trying to match the years based on the month in table1.adm_dt. This has the added bonus that Oracle can use an index on the table1.adm_dt column whereas your query would not use an index and would need separate function-based indexes for each of the EXTRACT functions for MONTH and YEAR.
Either:
SELECT t1.*
FROM table1 T1
LEFT OUTER JOIN table2 T2
ON (t1.code = t2.code
AND t1.adm_dt >= TO_DATE((t2.year - 1) || '-09-01', 'YYYY-MM-DD')
AND t1.adm_dt < TO_DATE(t2.year || '-09-01', 'YYYY-MM-DD')
)
WHERE t2.code IS NULL;
or:
SELECT *
FROM table1 T1
WHERE NOT EXISTS (
SELECT 1
FROM table2 T2
WHERE t1.code = t2.code
AND t1.adm_dt >= TO_DATE((t2.year - 1) || '-09-01', 'YYYY-MM-DD')
AND t1.adm_dt < TO_DATE(t2.year || '-09-01', 'YYYY-MM-DD')
);
Which, for your sample data, both output:
ROLLNO
CODE
ADM_DT
102
ABD
15-JAN-21 00.00.00.000
105
FED
21-SEP-21 00.00.00.000
101
ACD
12-DEC-21 00.00.00.000
db<>fiddle here
I have a table with business days BUSINESS_DAYS which has all the dates
I have another table with payment information and DUE_DATES
I want to return in my query the next business day IF the DUE_DATE is not a business day
SELECT SQ1.DUE_DATE, SQ2.DATE FROM
(SELECT * FROM
PAYMENTS
ORDER BY
DUE_DATE) SQ1,
(SELECT MIN(DATE) DATE FROM BUSINESS_DAYS WHERE SQ1.DUE_DATE <= DATE GROUP BY DATE) SQ2
Anyone can shed some light?
The way I see it, code you posted doesn't do what you wanted anyway (otherwise, you won't be asking a question at all). Therefore, I'd suggest another approach:
Altering the session (you don't have to do it; my database speaks Croatian so I'm switching to English; also, setting date format to display day name):
SQL> alter session set nls_date_language = 'english';
Session altered.
SQL> alter session set nls_date_format = 'dd.mm.yyyy, dy';
Session altered.
Two CTEs contain
business_days: as commented, only this year's July, weekends excluded, there are no holidays)
payments: two rows, one whose due date is a working day and another whose isn't
Sample data end at line #15, query you might be interested in begins at line #16. Its CASE expression check whether due_date is one of weekend days; if not, due date to be returned is exactly what it is. Otherwise, another SELECT statement returns the first (MIN) business day larger than due_date.
SQL> with
2 business_days (datum) as
3 -- for simplicity, only all dates in this year's July,
4 -- weekends excluded (as they aren't business days), no holidays
5 (select date '2021-07-01' + level - 1
6 from dual
7 where to_char(date '2021-07-01' + level - 1, 'dy')
8 not in ('sat', 'sun')
9 connect by level <= 31
10 ),
11 payments (id, due_date) as
12 (select 1, date '2021-07-14' from dual -- Wednesday, business day
13 union all
14 select 2, date '2021-07-25' from dual -- Sunday, non-business day
15 )
16 select p.id,
17 p.due_date current_due_date,
18 --
19 case when to_char(p.due_date, 'dy') not in ('sat', 'sun') then
20 p.due_date
21 else (select min(b.datum)
22 from business_days b
23 where b.datum > p.due_date
24 )
25 end new_due_date
26 from payments p
27 order by id;
ID CURRENT_DUE_DAT NEW_DUE_DATE
---------- --------------- ---------------
1 14.07.2021, wed 14.07.2021, wed --> Wednesday remains "as is"
2 25.07.2021, sun 26.07.2021, mon --> Sunday switched to Monday
SQL>
I have an Oracle table with data like below:
1. ID DATE
2. 12 02/11/2013
3. 12 02/12/2013
4. 13 02/11/2013
5. 13 02/12/2013
6. 13 02/13/2013
7. 13 02/14/2013
8. 14 02/11/2013
9. 14 02/12/2013
10. 14 02/13/2013
I need to find only those ID who has only Monday, Tuesday and Wednesday dates, so here only ID = 14 should be returned. I am using Oracle and dates are in format MM/DD/YYYY.
Please advice.
Regards,
Nitin
If date column is DATE datatype, then you can
select id
from your_table
group by id
having sum(case
when to_char(date_col,'fmday')
in ('monday','tuesday','wednesday') then 1
else 99
end) = 3;
EDIT: Corected the above code at the igr's observation
But this is ok only if you don't have a day twice for the same id.
If the column is varchar2 then the condition becomes to_char(to_date(your_col,'mm/dd/yyyy'),'fmday') in ...
A more robust code would be:
select id
from(
select id, date_col
from your_table
group by id, date_col
)
group by id
having sum(case
when to_char(date_col,'fmday', 'NLS_DATE_LANGUAGE=ENGLISH')
in ('monday','tuesday','wednesday') then 1
else 99
end) = 3;
select id
from (
select
id,
sum (case when to_char(dt, 'D', 'nls_territory=AMERICA') between 1 and 3 then 1 else -1 end) AS cnt
from t
group by id
)
where cnt=3
NOTE: I assumed (id,dt) is unique - no two lines with same id and date.
do something like
SELECT * FROM your_table t
where to_char(t.DATE, 'DY') in ('whatever_day_abbreviation_day_you_use');
alternatively if you prefer you could use day numbers like:
SELECT * FROM your_table t
where to_number(to_char(d.ts, 'D')) in (1,2,3);
if you'd like to avoid ID repetition add DISTINCTION
SELECT DISTINCT ID FROM your_table t
where to_number(to_char(d.ts, 'D')) in (1,2,3);
If I run the following statement as part of a sql script
-- create the pivot_sales_data table
CREATE TABLE pivot_sales_data AS
SELECT *
FROM (
SELECT month, prd_type_id, amount
FROM all_sales
WHERE year = 2003
AND prd_type_id IN (1, 2, 3)
)
PIVOT (
SUM(amount) FOR month IN (1 AS JAN, 2 AS FEB, 3 AS MAR, 4 AS APR)
)
ORDER BY prd_type_id;
I get the ORA-00933: SQL Command nor properly ended error. What am I missing here?
Your pivot doesn't really work. I'm specifically thinking about:
FOR month IN (1 AS JAN, 2 AS FEB, 3 AS MAR, 4 AS APR)
In doesn't really work that way. You either want:
FOR month IN ('JAN', 'FEB', 'MAR', 'APR')
-- or
FOR month IN (1,2,3,4)
Is there a way in Oracle that can pull the FY? I used the script below to pull just two FY. Mytable date range is from FY1998 to FY2009.
SELECT 'FY2008' as FY,
Site,
COUNT(*)
FROM mytable
WHERE date >='10-OCT-2007'
AND date <'10-OCT-2008'
GROUP BY site
SELECT 'FY2008' as FY,
Site,
COUNT(*)
FROM mytable
WHERE date >='10-OCT-2008'
AND date <'10-OCT-2009'
GROUP BY site
Pulling two FY is OK but it's too much repeatative when pulling more than 10 FY.
Add 83 days to your date and truncate it to whole year:
select 'FY'||TRUNC(date + 83, 'YYYY') as FY, Site, count(*)
from mytable
group by 'FY'||TRUNC(date + 83, 'YYYY'), site
Assuming Oracle 9i+, use a CASE expression:
SELECT CASE
WHEN TO_CHAR(t.date, ) = 10 AND EXTRACT(DAY FROM t.date) >= 10 THEN
'FY' || EXTRACT(YEAR FROM t.date) + 1
WHEN TO_CHAR(t.date, ) > 10 THEN
'FY' || EXTRACT(YEAR FROM t.date) + 1
ELSE
'FY' || EXTRACT(YEAR FROM t.date)
END AS FY,
t.site,
COUNT(*)
FROM YOUR_TABLE t
GROUP BY t.site, FY
And for completeness, in addition to #eumiro answer. In countries (such as Australia) which have a financial year running from 1 July to 30 June, you can replace the 83 with 184.
A few options:
You can use the to_char function here. Check this link for an explanation:
http://www.techonthenet.com/oracle/functions/to_char.php
You may also try using a case statement
select case when date >='10-OCT-2007' and date <'10-OCT-2008' then 'FY08'
when date >='10-OCT-2008' and date <'10-OCT-2009' then 'FY09'
else 'Other' end as fiscal_year, count(*)
from mytable
group by case when date >='10-OCT-2007' and date <'10-OCT-2008' then 'FY08'
when date >='10-OCT-2008' and date <'10-OCT-2009' then 'FY09'
else 'Other' end
Ultimately, if you have create table privileges you may want to consider making a date lookup table. Search for "date dimension" in data warehousing guides.
For example:
Your table would have
date, date_desc, fiscal_year, etc....
then you could just join and group by fiscal year, or whatever else you want.
Here is another way to easily determine the Fiscal Year of a date for those who's Fiscal Year runs from July to June:
SELECT 'FY'||TO_CHAR(ROUND(your_date_here,'YEAR'),'YY') AS FY