Wednesday, August 8, 2018

When to use self-join?


SELF JOIN is used to join a table to itself as if the table were two tables; temporarily renaming at least one table in the SQL statement.

Eg: Write a SQL query to find the products whose sales decreased in 2012 compared to 2011?

Refer data below:

CREATE TABLE PRODUCTS
(
       PRODUCT_ID     INTEGER,
       PRODUCT_NAME   VARCHAR(30)
);
CREATE TABLE SALES
(
       SALE_ID        INTEGER,
       PRODUCT_ID     INTEGER,
       YEAR           INTEGER,
       Quantity       INTEGER,
       PRICE          INTEGER
);     

INSERT INTO PRODUCTS VALUES ( 100, 'Santoor');
INSERT INTO PRODUCTS VALUES ( 200, 'Sandal');
INSERT INTO PRODUCTS VALUES ( 300, 'Lux');
INSERT INTO PRODUCTS VALUES ( 400, 'Medimix');

INSERT INTO SALES VALUES ( 1, 100, 2010, 25, 6000);
INSERT INTO SALES VALUES ( 2, 100, 2011, 16, 6000);
INSERT INTO SALES VALUES ( 3, 100, 2012, 8,  6000);
INSERT INTO SALES VALUES ( 4, 200, 2010, 10, 9000);
INSERT INTO SALES VALUES ( 5, 200, 2011, 15, 9000);
INSERT INTO SALES VALUES ( 6, 200, 2012, 20, 9000);
INSERT INTO SALES VALUES ( 7, 300, 2010, 20, 8000);
INSERT INTO SALES VALUES ( 8, 300, 2011, 18, 8000);
INSERT INTO SALES VALUES ( 9, 300, 2012, 20, 8000);

Query:

SELECT PRODUCTS.PRODUCT_NAME
FROM   PRODUCTS ,
       SALES currsales,
       SALES prevsales
WHERE  PRODUCTS.PRODUCT_ID = currsales.PRODUCT_ID
AND    currsales.YEAR = 2012
AND    prevsales.YEAR = 2011
AND    currsales.PRODUCT_ID = prevsales.PRODUCT_ID
AND   currsales.QUANTITY < prevsales.QUANTITY;

when to use 'select 1 from table'?

select 1 from table
will return a column of 1's for every row in the table. Use it with a where statement to check for an entry for a given key:

if exists(select 1 from table where some_column = 'some_value')

Eg: 
Consider the tables and data given below.
CREATE TABLE PRODUCTS
(
       PRODUCT_ID     INTEGER,
       PRODUCT_NAME   VARCHAR(30)
);
CREATE TABLE SALES
(
       SALE_ID        INTEGER,
       PRODUCT_ID     INTEGER,
       YEAR           INTEGER,
       Quantity       INTEGER,
       PRICE          INTEGER
);       

INSERT INTO PRODUCTS VALUES ( 100, 'Santoor');
INSERT INTO PRODUCTS VALUES ( 200, 'Sandal');
INSERT INTO PRODUCTS VALUES ( 300, 'Lux');
INSERT INTO PRODUCTS VALUES ( 400, 'Medimix');

INSERT INTO SALES VALUES ( 1, 100, 2010, 25, 6000);
INSERT INTO SALES VALUES ( 2, 100, 2011, 16, 6000);
INSERT INTO SALES VALUES ( 3, 100, 2012, 8,  6000);
INSERT INTO SALES VALUES ( 4, 200, 2010, 10, 9000);
INSERT INTO SALES VALUES ( 5, 200, 2011, 15, 9000);
INSERT INTO SALES VALUES ( 6, 200, 2012, 20, 9000);
INSERT INTO SALES VALUES ( 7, 300, 2010, 20, 8000);
INSERT INTO SALES VALUES ( 8, 300, 2011, 18, 8000);
INSERT INTO SALES VALUES ( 9, 300, 2012, 20, 8000);

Write a SQL query to find the products which having sales?
select product_name from products where exists (SELECT 1 FROM SALES WHERE SALES.PRODUCT_ID = PRODUCTS.PRODUCT_ID);

Write a SQL query to find the products which does not have sales at all?
select product_name from products where not exists (SELECT 1 FROM SALES WHERE SALES.PRODUCT_ID = PRODUCTS.PRODUCT_ID);

Monday, August 6, 2018

Find second highest salary in database

Query 1
select max(sal) from emp where sal <(select max(sal) from emp);
Query 2
SELECT MAX(Salary) FROM Employee
WHERE Salary NOT IN (SELECT MAX(Salary) FROM Employee );
Query 3
SELECT salary FROM Employee
ORDER BY salary DESC
LIMIT 1,1;
Query 4
SELECT TOP 1 Salary
FROM (
      SELECT DISTINCT TOP N Salary
      FROM Employee
      ORDER BY Salary DESC
      ) AS Emp
ORDER BY Salary;
Query 5
select top 1 sal from (select top 2 sal from emp order by sal desc) as emp order by sal;
Query 6
select min(sal) as sal from (select top 2 sal from emp order by sal desc) as emp;

well, if I want to find top 50th sal from emp table. what should I do?
Here comes the benefit of Ranking in Database which is one of the advanced aggregate functions.

select * FROM (

select EmpID, Salary
,rank() over (order by Salary DESC) emprank
from emp
)
WHERE emprank = N;

If the ORDER BY clause cannot distinguish between two rows, it will give them different rankings (randomly).
RANK() and DENSE_RANK() will give the same ranking to rows that cannot be distinguished by the ORDER BY clause
DENSE_RANK() will always generate a contiguous sequence of ranks (1,2,3,...), whereas RANK() will leave gaps after two or more rows with the same rank ( if two students win the gold medal, there is no second place, only third).

Detailed Example

CREATE TABLE PRODUCTS
(
       PRODUCT_ID     INTEGER,
       PRODUCT_NAME   VARCHAR(30)
);
CREATE TABLE SALES
(
       SALE_ID        INTEGER,
       PRODUCT_ID     INTEGER,
       YEAR           INTEGER,
       Quantity       INTEGER,
       PRICE          INTEGER
);       

INSERT INTO PRODUCTS VALUES ( 100, 'Santoor');
INSERT INTO PRODUCTS VALUES ( 200, 'Sandal');
INSERT INTO PRODUCTS VALUES ( 300, 'Lux');
INSERT INTO PRODUCTS VALUES ( 400, 'Medimix');

INSERT INTO SALES VALUES ( 1, 100, 2010, 25, 6000);
INSERT INTO SALES VALUES ( 2, 100, 2011, 16, 6000);
INSERT INTO SALES VALUES ( 3, 100, 2012, 8,  6000);
INSERT INTO SALES VALUES ( 4, 200, 2010, 10, 9000);
INSERT INTO SALES VALUES ( 5, 200, 2011, 15, 9000);
INSERT INTO SALES VALUES ( 6, 200, 2012, 20, 9000);
INSERT INTO SALES VALUES ( 7, 300, 2010, 20, 8000);
INSERT INTO SALES VALUES ( 8, 300, 2011, 18, 8000);
INSERT INTO SALES VALUES ( 9, 300, 2012, 20, 8000);

Write a query to select the top product sold in each year? 

Finding rank for each product in each year
Query 1
step 1
SELECT P.PRODUCT_NAME,
       S.YEAR,s.Quantity,
       RANK() OVER (
              PARTITION BY S.YEAR 
              ORDER BY S.QUANTITY DESC
              ) PRODRNK
FROM   PRODUCTS P,
       SALES S
WHERE  P.PRODUCT_ID = S.PRODUCT_ID

step 2

SELECT PRODUCT_NAME,
       YEAR
FROM
(
SELECT P.PRODUCT_NAME,
       S.YEAR,s.Quantity,
       RANK() OVER (
              PARTITION BY S.YEAR 
              ORDER BY S.QUANTITY DESC
              ) PRODRNK
FROM   PRODUCTS P,
       SALES S
WHERE  P.PRODUCT_ID = S.PRODUCT_ID
) Details
WHERE PRODRNK = 1;

Query 2 (without ranking function)
step 1
SELECT YEAR,
MAX(QUANTITY) QUAN
FROM SALES
GROUP BY YEAR
step 2
SELECT P.PRODUCT_NAME,
S.YEAR,
S.QUANTITY
FROM
(
SELECT YEAR,
MAX(QUANTITY) QUAN
FROM SALES
GROUP BY YEAR
)maximum, SALES S,
PRODUCTS P
WHERE maximum.YEAR = S.YEAR
AND maximum.QUAN = S.QUANTITY
AND S.PRODUCT_ID = P.PRODUCT_ID;

Recursive CTE – Sql Server - very useful links

CTE(common table Expression)
It is a temporary named result set which can refer within a SELECT, INSERT, UPDATE, DELETE or in a CREATE VIEW statement, as part of the view’s SELECT query statement. From SQL Server 2008 on wards, it can be used with MERGE statement also.
SQL Server supports two types of CTEs-recursive and nonrecursive. A recursive CTE query must contain at least two members (statements), connected by the UNION ALL, UNION, INTERSECT, or EXCEPT operator.
SQL WITH clause

The SQL WITH clause was introduced by Oracle in the Oracle 9i release 2 database. The SQL WITH clause allows to give a sub-query block which can be referenced in several places within the main SQL query.It is used for defining a temporary relation such that the output of this temporary relation is available and is used by the query that is associated with the WITH clause.

General syntax
WITH ctealias (column_aliases)  
AS  

cte_query_definition1   --initialization 
UNION ALL 
cte_query_definition2 --recursive execution 
)  
SELECT * FROM ctealias;

http://sqlhints.com/2015/09/05/recursive-cte-sql-server/
https://www.mssqltips.com/sqlservertip//recursive-queries-using-common-table-expressions-cte-in-sql-server/

Direct recursion occurs when a method invokes itself. Indirect recursion occurs when a method invokes another method, eventually resulting in the original method being invoked again.

GEN AI

  Stay Tuned....