SQL query to fetch details when one of value is missing - sql

Consider a table with entries for students:
cloumn1 key value
-------------------------------
john age 23
john salary 100
John rollno 12
Raj age 24
Raj rollno 10
I want to get result of salary value when queried on salary and student
name.
It is always queried on salary and student. For the second student since salary record itself is not there. I am facing the issue in fetching the records
SELECT
a.id, b.location, c.value
FROM
boys A, school B,details c
WHERE
A.id = B.id
c.id = a.id
c.key = salary
Request every one to throw your solutions
Thanks in advance

SELECT id,
MAX( CASE key WHEN 'salary' THEN value END ) AS salary
FROM details
GROUP BY id
or
SELECT *
FROM details
PIVOT ( MAX( value )
FOR key IN (
'salary' AS salary,
'rollno' AS rollno,
'age' AS age
) );

Related

How to display the related records in a single row in Oracle SQL?

I wrote a query joining two tables and I got a below resultset:
SELECT emp.employee_id,
dept.department_name,
dept.department_id
FROM employee emp,
department dept
WHERE emp.department_id = dept.department_id;
Employee_ID Department Department_ID
Mark Sales D1
Mark Marketing D2
Justin Textiles D3
Kimberley (null) (null)
However, I need to display below output with one new field called 'Status'.Mark can work in both the departments and so the count is "2" and the status will be 'Y' ( displaying of any one record is okay) . Justin works in only one department and count is 1 and status should be 'N'. Kimberley does not work anywhere and count is 0 and status should be 'N'.
Expected output:
Employee_ID Department Department_ID Status
Mark Sales D1 Y
Justin Textiles D3 N
Kimberley (null) (null) N
Please help.
I understand that you want to display the first department per user, and add a flag that indicates whether the employee belongs to at least one other department.
You can use window functions:
select
employee_id,
department_name,
department_id
case when cnt <= 1 then 'N' else 'Y' end status
from (
select
emp.employee_id,
dept.department_name,
dept.department_id,
row_number() over(partition by emp.employee_id order by dept.department_id) rn,
count(*) over(partition by emp.employee_id) cnt
from
employee emp
left join department dept on emp.department_id = dept.department_id
) t
where rn = 1
Side note: always use explicit joins (with the on keyword) instead of old-school, implicit joins (with commas in the from clause), whose syntax is harder to read and maintain.
I think this can be easily achieved using group by and keep clause with max as following:
SELECT emp.employee_id,
Max(dept.department_name) keep (dense_rank first order by dept.department_id) as department_name,
Max(dept.department_id) keep (dense_rank first order by dept.department_id) as department_id,
case when count(1) > 1 then 'Y' else 'N' end as status
FROM employee emp
LEFT JOIN department dept ON emp.department_id = dept.department_id
GROUP BY emp.employee_id;
Cheers!!

Creating dynamic query which has also has a sub-query

I use two queries in SQL Server, which I would like to combine and create a single query. Tried few options but of not much success.
Query 1
select emp_id, name, age
from employee
where age > 50
Query 2
select dept_id, dept_name
from department
where emp_id = 'COMPANY.ID' + emp_id
The issue in combining the two queries is, though query 1 can return multiple rows, I can't use a subquery to directly use emp_id from query 1 in query 2 since the emp_id in query 2 has a prefix of 'COMPANY.ID.'+emp_id. Any suggestions?
COMPANY.ID is a constant that gets prefixed to emp_id before saving it in department table.
Example employee table
emp_id name age
-----------------------------
123 John 45
345 Susan 34
789 Pat 66
Example department table
emp_id dept_id dept_name
-----------------------------------------------------------------------
COMPANY.ID.123 123 Accounting
COMPANY.ID.345 123 Accounting
Hope these examples help understand my dataset
I understand that you are trying to pull out the departments that have at least one employee older than 50.
One solution would be to use an EXISTS condition with a correlated subquery:
SELECT dept_id, dept_name
FROM department d
WHERE EXISTS (
SELECT 1
FROM employee e
WHERE
CONCAT('COMPANY.ID.', e.emp_id) = d.emp_id
AND e.age > 50
)
Demo on DB Fiddle
Is this what you want as
Query 2 is totally wrong and would never match instead would have used like %CompanyId%
select distinct dept_id, dept_name
from
department where empid IN (
select emp_id from
employee where age > 50 and empid
like '%CompanyId%' )
You can combine the two tables using join
SELECT d.dept_id, d.dept_name
FROM department d
INNER JOIN employee e
ON CONCAT('COMPANY.ID.', e.emp_id) = d.emp_id
WHERE e.age > 50

Name of Teacher with Highest Wage - recursive CTE

I am trying to get the max salary of each dept and display that teacher by first name as a separate column. So dept 1 may have 4 rows but one name showing for max salary. I'm Using SQL SERVER
With TeacherList AS(
Select Teachers.FirstName,Teachers.LastName,
Teachers.FacultyID,TeacherID, 1 AS LVL,PrincipalTeacherID AS ManagerID
FROM dbo.Teachers
WHERE PrincipalTeacherID IS NULL
UNION ALL
Select Teachers.FirstName,Teachers.LastName,
Teachers.FacultyID,Teachers.TeacherID, TeacherList.LVL +
1,Teachers.PrincipalTeacherID
FROM dbo.Teachers
INNER JOIN TeacherList ON Teachers.PrincipalTeacherID =
TeacherList.TeacherID
WHERE Teachers.PrincipalTeacherID IS NOT NULL)
SELECT * FROM TeacherList;
SAMPLE OUTPUT :
Teacher First Name | Teacher Last Name | Faculty| Highest Paid In Faculty
Eric Smith 1 Eric
Alex John 1 Eric
Jessica Sewel 1 Eric
Aaron Gaye 2 Aaron
Bob Turf 2 Aaron
I'm not sure from your description but this will return all teachers and the last row is the name of the teacher with the highest pay on the faculty.
select tr.FirstName,
tr.LastName,
tr.FacultyID,
th.FirstName
from Teachers tr
join (
select FacultyID, max(pay) highest_pay
from Teachers
group by FacultyID
) t on tr.FacultyID = t.FacultyID
join Teachers th on th.FacultyID = t.FacultyID and
th.pay = t.highest_pay
this will produce an unexpected result (duplicate rows) if there are more persons with the highest salary on the faculty. In such case you may use window functions as follows:
select tr.FirstName,
tr.LastName,
tr.FacultyID,
t.FirstName
from Teachers tr
join
(
select t.FirstName,
t.FacultyID
from
(
select t.*,
row_number() over (partition by FacultyID order by pay desc) rn
from Teachers t
) t
where t.rn = 1
) t on tr.FacultyID = t.FacultyID
This will display just one random teacher from faculty with highest salary.
dbfiddle demo
You can do this with a CROSS APPLY.
SELECT FirstName, LastName, FacultyID, HighestPaid
FROM Teachers t
CROSS APPLY (SELECT TOP 1 FirstName AS HighestPaid
FROM Teachers
WHERE FacultyID = t.FacultyID
ORDER BY Salary DESC) ca

SQL Query using Group by 4

I have tables which looks like below.
Employee table
Date Employee ID Employer ID Salary
2/3/2011 10 20 45666
3/12/2009 43 53 2356
Employer Table
Employer ID State
53 OH
42 MI
Trying to get the total salary by month and by state using group by clause. But not getting the results. what am i doing wrong?? any help appreciated
select date, sum(salary) from employee
group by to_char(date,'MON')
select sum(salary) from employee A, Employer B
where A.employer id=B.employer id
group by B.state
Also i need to get the top 10 distinct employee ids based on their salary
select DISTINCT employee id from employee
where rownum<=10
order by salary desc
You have to group by the exact expression in your select list, e.g.,
select to_char(date,'MON'), sum(salary)
from employee
group by to_char(date,'MON');
You probably want to include the state in your second query:
select b.state, sum(salary)
from employee A, Employer B
where A.employer_id=B.employer_id
group by B.state;
Generally speaking, stating in your question that you're "not getting the results" is not very helpful to the folks you're asking help of. Please provide any error messages or output that describes what "not getting the results" means.

how to fetch top distinct data in sqlserver

I have a table named employee_salary, with three columns: empsal_id, empsal_name and empsal_sal. The data is as follows:
empsal_id empsal_name empsal_sal
1 dilip 14000
2 santosh 20000
3 amit 32000
4 dilip 22000
5 amit 38000
6 santosh 25000
7 dilip 30000
The empsal_id is an Identity column with a Seed and an Increment of 1, and is the Primary Key. I want to return the name and current salary of each employee. Salary can decrease as well as increase, so current does not necessarily mean highest.
So I need the following output:
empname emp_sal
dilip 30000
amit 38000
santosh 25000
I am using Microsoft SQL Server, and I have to do this in a single query.
This query will return each employee, along with their highest salary:
SELECT
empsal_name, MAX(empsal_sal)
FROM
employee
GROUP BY
empsal_name
This query will return each employee, along with their current salary (i.e. the salary with the highest empsal_id:
SELECT
empsal_name, empsal_sal
FROM
employee e1
WHERE
empsal_id =
(SELECT MAX(empsal_id)
FROM employee e2
WHERE e1.empsal_name=e2.empsal_name)
Personally, I think you would be better off using an effective date column (e.g. empsal_effectivedate) to determine which record is the most current, so this query will return each employee, along with their current salary (i.e. the salary with the most recent empsal_effectivedate), assuming there is an empsal_effectivedate field:
SELECT
empsal_name, empsal_sal
FROM
employee e1
WHERE
empsal_effectivedate =
(SELECT MAX(empsal_effectivedate)
FROM employee e2
WHERE e1.empsal_name=e2.empsal_name)
Assuming there is also an ID in the table and also assuming that the larger this ID is the most recent the salary is for that employee you can do
SELECT DISTINCT
e.empname,
(SELECT TOP 1
emp_sal
FROM
employee s
WHERE
s.empname = e.empname
ORDER BY
recid DESC) AS emp_sal
FROM
employee e
(also assuming that empname is unique for an employee)
because of the many assumptions though : you should probably post all the columns of the table and what they mean ..
SELECT empname, MAX(emp_sal)
FROM employee
GROUP BY empname
UPDATED:
SELECT DISTINCT EmpA.empname,
EmpA.emp_sal
FROM Employee AS EmpA
INNER JOIN ( SELECT EmpName, MAX(recID) AS recid
FROM Employee
GROUP BY EmpName
) AS EmpB ON EmpA.recid = EmpB.recid;
You need a date field to determine the latest inserted row . In case if the table is linked to some other table which has date column in it .Then its pretty easy to fetch the current data .
For Example
Employee Table
{
EmpName varchar(30) PK,
EmpAddress varchar(255) ,
Company varchar(30),
CurrentTimeStamp Datetime
}
Salary Table
{
EmpName varchar(30) FK,
EmpSalary int
}
To get the Latest record use the CTE function
With LatestSal(EmpName ,EmpSalary)
AS
(
Select row_number() over (PARTITION BY b.[EmpName], order by CurrentTimestamp DESC) as seq
b.EmpName,b.EmpSalary
From Employee as a,
Salary as b
on a.[EmpName]=b.[EmpName]
)
Select EmpName,EmpSalary
from LatestSal
where seq=1