Write a query to get the top 5 products based on the quantity sold without using the row_number analytical function? The source data looks as
Products, quantity_sold, year
-----------------------------
A, 200, 2009
B, 155, 2009
C, 455, 2009
D, 620, 2009
E, 135, 2009
F, 390, 2009
G, 999, 2010
H, 810, 2010
I, 910, 2010
J, 109, 2010
L, 260, 2010
M, 580, 2010
Solution:
SELECT products,
quantity_sold,
year
FROM
(
SELECT products,
quantity_sold,
year,
rownum r
from t
ORDER BY quantity_sold DESC
)A
WHERE r <= 5;
Write a query to produce the same output using row_number analytical function?
Solution:
SELECT products,
quantity_sold,
year
FROM
(
SELECT products,
quantity_sold,
year,
row_number() OVER(
ORDER BY quantity_sold DESC) r
from t
)A
WHERE r <= 5;
write a query to get the top 5 products in each year based on the quantity sold?
Solution:
SELECT products,
quantity_sold,
year
FROM
(
SELECT products,
quantity_sold,
year,
row_number() OVER(
PARTITION BY year
ORDER BY quantity_sold DESC) r
from t
)A
WHERE r <= 5;
Load the below products table into the target table.
CREATE TABLE PRODUCTS
(
PRODUCT_ID INTEGER,
PRODUCT_NAME VARCHAR2(30)
);
INSERT INTO PRODUCTS VALUES ( 100, 'Nokia');
INSERT INTO PRODUCTS VALUES ( 200, 'IPhone');
INSERT INTO PRODUCTS VALUES ( 300, 'Samsung');
INSERT INTO PRODUCTS VALUES ( 400, 'LG');
INSERT INTO PRODUCTS VALUES ( 500, 'BlackBerry');
INSERT INTO PRODUCTS VALUES ( 600, 'Motorola');
COMMIT;
SELECT * FROM PRODUCTS;
PRODUCT_ID PRODUCT_NAME
-----------------------
100 Nokia
200 IPhone
300 Samsung
400 LG
500 BlackBerry
600 Motorola
The requirements for loading the target table are:
Select only 2 products randomly.
Do not select the products which are already loaded in the target table with in the last 30 days.
Target table should always contain the products loaded in 30 days. It should not contain the products which are loaded prior to 30 days.
Solution:
First we will create a target table. The target table will have an additional column INSERT_DATE to know when a product is loaded into the target table. The target
table structure is
CREATE TABLE TGT_PRODUCTS
(
PRODUCT_ID INTEGER,
PRODUCT_NAME VARCHAR2(30),
INSERT_DATE DATE
);
The next step is to pick 5 products randomly and then load into target table. While selecting check whether the products are there in the
INSERT INTO TGT_PRODUCTS
SELECT PRODUCT_ID,
PRODUCT_NAME,
SYSDATE INSERT_DATE
FROM
(
SELECT PRODUCT_ID,
PRODUCT_NAME
FROM PRODUCTS S
WHERE NOT EXISTS (
SELECT 1
FROM TGT_PRODUCTS T
WHERE T.PRODUCT_ID = S.PRODUCT_ID
)
ORDER BY DBMS_RANDOM.VALUE --Random number generator in oracle.
)A
WHERE ROWNUM <= 2;
The last step is to delete the products from the table which are loaded 30 days back.
DELETE FROM TGT_PRODUCTS
WHERE INSERT_DATE < SYSDATE - 30;
Load the below CONTENTS table into the target table.
CREATE TABLE CONTENTS
(
CONTENT_ID INTEGER,
CONTENT_TYPE VARCHAR2(30)
);
INSERT INTO CONTENTS VALUES (1,'MOVIE');
INSERT INTO CONTENTS VALUES (2,'MOVIE');
INSERT INTO CONTENTS VALUES (3,'AUDIO');
INSERT INTO CONTENTS VALUES (4,'AUDIO');
INSERT INTO CONTENTS VALUES (5,'MAGAZINE');
INSERT INTO CONTENTS VALUES (6,'MAGAZINE');
COMMIT;
SELECT * FROM CONTENTS;
CONTENT_ID CONTENT_TYPE
-----------------------
1 MOVIE
2 MOVIE
3 AUDIO
4 AUDIO
5 MAGAZINE
6 MAGAZINE
The requirements to load the target table are:
Load only one content type at a time into the target table.
The target table should always contain only one contain type.
The loading of content types should follow round-robin style. First MOVIE, second AUDIO, Third MAGAZINE and again fourth Movie.
Solution:
First we will create a lookup table where we mention the priorities for the content types. The lookup table “Create Statement” and data is shown below.
CREATE TABLE CONTENTS_LKP
(
CONTENT_TYPE VARCHAR2(30),
PRIORITY INTEGER,
LOAD_FLAG INTEGER
);
INSERT INTO CONTENTS_LKP VALUES('MOVIE',1,1);
INSERT INTO CONTENTS_LKP VALUES('AUDIO',2,0);
INSERT INTO CONTENTS_LKP VALUES('MAGAZINE',3,0);
COMMIT;
SELECT * FROM CONTENTS_LKP;
CONTENT_TYPE PRIORITY LOAD_FLAG
---------------------------------
MOVIE 1 1
AUDIO 2 0
MAGAZINE 3 0
Here if LOAD_FLAG is 1, then it indicates which content type needs to be loaded into the target table. Only one content type will have LOAD_FLAG as 1. The other content types will have LOAD_FLAG as 0. The target table structure is same as the source table structure.
The second step is to truncate the target table before loading the data
TRUNCATE TABLE TGT_CONTENTS;
The third step is to choose the appropriate content type from the lookup table to load the source data into the target table.
INSERT INTO TGT_CONTENTS
SELECT CONTENT_ID,
CONTENT_TYPE
FROM CONTENTS
WHERE CONTENT_TYPE = (SELECT CONTENT_TYPE FROM CONTENTS_LKP WHERE LOAD_FLAG=1);
The last step is to update the LOAD_FLAG of the Lookup table.
UPDATE CONTENTS_LKP
SET LOAD_FLAG = 0
WHERE LOAD_FLAG = 1;
UPDATE CONTENTS_LKP
SET LOAD_FLAG = 1
WHERE PRIORITY = (
SELECT DECODE( PRIORITY,(SELECT MAX(PRIORITY) FROM CONTENTS_LKP) ,1 , PRIORITY+1)
FROM CONTENTS_LKP
WHERE CONTENT_TYPE = (SELECT DISTINCT CONTENT_TYPE FROM TGT_CONTENTS)
);
How to retrieve 2nd highest sal in each departement from emp and dept tables using GROUP BY?
SELECT e.DeptNo, MAX(e.Sal),d.DeptName Salary
FROM Emp e left outer join dept d ON e.DeptNo=d.DeptNo
WHERE e.Sal <
(SELECT MAX(Sal)
FROM Emp
WHERE DeptNo = e.DeptNo)
GROUP BY e.DeptNo,d.DeptName
Find the 3rd MAX and MIN salary in the emp table?
select distinct sal from emp e1 where 3 = (select count(distinct sal) from emp e2 where e1.sal <= e2.sal);
select distinct sal from emp e1 where 3 = (select count(distinct sal) from emp e2where e1.sal >= e2.sal);
If there are two tables emp1 and emp2, and both have common record. How can I fetch all the records but common records only once?
(Select * from emp) Union (Select * from emp1)
How to fetch only common records from two tables emp and emp1?
(Select * from emp) Intersect (Select * from emp1)
How can I retrive all records of emp1 those should not present in emp2?
(Select * from emp) Minus (Select * from emp1)
Get the first day of the month?
SELECT e.DeptNo, MAX(e.Sal),d.DeptName Salary
FROM Emp e left outer join dept d ON e.DeptNo=d.DeptNo
WHERE e.Sal <
(SELECT MAX(Sal)
FROM Emp
WHERE DeptNo = e.DeptNo)
GROUP BY e.DeptNo,d.DeptName
Find the 3rd MAX and MIN salary in the emp table?
select distinct sal from emp e1 where 3 = (select count(distinct sal) from emp e2 where e1.sal <= e2.sal);
select distinct sal from emp e1 where 3 = (select count(distinct sal) from emp e2where e1.sal >= e2.sal);
If there are two tables emp1 and emp2, and both have common record. How can I fetch all the records but common records only once?
(Select * from emp) Union (Select * from emp1)
How to fetch only common records from two tables emp and emp1?
(Select * from emp) Intersect (Select * from emp1)
How can I retrive all records of emp1 those should not present in emp2?
(Select * from emp) Minus (Select * from emp1)
Get the first day of the month?
Quickly returns the first day of current month. Instead of current month you want to find first day of month where a date falls, replace SYSDATE with any date column/value.
SELECT TRUNC (SYSDATE, 'MONTH') "First day of current month"
FROM DUAL;
Get the last day of the month?
This query is similar to above but returns last day of current month. One thing worth noting is that it automatically takes care of leap year. So if you have 29 days in Feb, it will return 29/2. Also similar to above query replace SYSDATE with any other date column/value to find last day of that particular month.
SELECT TRUNC (LAST_DAY (SYSDATE)) "Last day of current month"
FROM DUAL;
Get the first day of the Year
First day of year is always 1-Jan. This query can be use in stored procedure where you quickly want first day of year for some calculation.
SELECT TRUNC (SYSDATE, 'YEAR') "Year First Day" FROM DUAL;
Get the last day of the year
Similar to above query. Instead of first day this query returns last day of current year.
SELECT ADD_MONTHS (TRUNC (SYSDATE, 'YEAR'), 12) - 1 "Year Last Day" FROM DUAL
Get number of days in current month
Now this is useful. This query returns number of days in current month. You can change SYSDATE with any date/value to know number of days in that month.
SELECT CAST (TO_CHAR (LAST_DAY (SYSDATE), 'dd') AS INT) number_of_days
FROM DUAL;
Get number of days left in current month
Below query calculates number of days left in current month.
SELECT SYSDATE,
LAST_DAY (SYSDATE) "Last",
LAST_DAY (SYSDATE) - SYSDATE "Days left"
FROM DUAL;
Get number of days between two dates
Use this query to get difference between two dates in number of days.
SELECT ROUND ( (MONTHS_BETWEEN ('01-Feb-2014', '01-Mar-2012') * 30), 0)
num_of_days
FROM DUAL;
OR
SELECT TRUNC(sysdate) - TRUNC(e.hire_date) FROM employees;
Use second query if you need to find number of days since some specific date. In this example number of days since any employee is hired.
Display each months start and end date upto last month of the year
This clever query displays start date and end date of each month in current year. You might want to use this for certain types of calculations.
SELECT ADD_MONTHS (TRUNC (SYSDATE, 'MONTH'), i) start_date,
TRUNC (LAST_DAY (ADD_MONTHS (SYSDATE, i))) end_date
FROM XMLTABLE (
'for $i in 0 to xs:int(D) return $i'
PASSING XMLELEMENT (
d,
FLOOR (
MONTHS_BETWEEN (
ADD_MONTHS (TRUNC (SYSDATE, 'YEAR') - 1, 12),
SYSDATE)))
COLUMNS i INTEGER PATH '.');
Get number of seconds passed since today (since 00:00 hr)
SELECT (SYSDATE - TRUNC (SYSDATE)) * 24 * 60 * 60 num_of_sec_since_morning
FROM DUAL;
Get number of seconds left today (till 23:59:59 hr)
SELECT (TRUNC (SYSDATE+1) - SYSDATE) * 24 * 60 * 60 num_of_sec_left
FROM DUAL;
Check if a table exists in the current database schema
A simple query that can be used to check if a table exists before you create it. This way you can make your create table script rerunnable. Just replace table_name with actual table you want to check. This query will check if table exists for current user (from where the query is executed).
SELECT table_name
FROM user_tables
WHERE table_name = 'TABLE_NAME';
Check if a column exists in a table
Simple query to check if a particular column exists in table. Useful when you tries to add new column in table using ALTER TABLE statement, you might wanna check if column already exists before adding one.
SELECT column_name AS FOUND
FROM user_tab_cols
WHERE table_name = 'TABLE_NAME' AND column_name = 'COLUMN_NAME';
Showing the table structure
This query gives you the DDL statement for any table. Notice we have pass ‘TABLE’ as first parameter. This query can be generalized to get DDL statement of any database object. For example to get DDL for a view just replace first argument with ‘VIEW’ and second with your view name and so.
SELECT DBMS_METADATA.get_ddl ('TABLE', 'TABLE_NAME', 'USER_NAME') FROM DUAL;
Post a Comment