I have made a view of 2 tables - Department Master and Employee Master.
This is the table
Emp_Id Emp_Name Salary Dept_Id Dept
1 Chandan 10000.00 1 Mechnical
2 Sudhir 11000.00 1 Mechnical
3 Rahul 20000.00 1 Mechnical
4 Kavish 15000.00 1 Mechnical
5 sapin 23000.00 2 Computer
6 Kavita 23200.00 2 Computer
7 amit 50000.00 2 Computer
I want to get Maximum salary with department name and Employee Name
I used this this group by query as follows
select MAX(Emp_Salery) as Emp_Sal from V_New_Emp_Master group by Dept_Id
I am getting max salery , but when when I add Emp_Name column I get an error as followes
SQL query
select MAX(Emp_Salery),Emp_Name as Emp_Sal from V_New_Emp_Master group by Dept_Id
Error:
Msg 8120, Level 16, State 1, Line 1
Column 'V_New_Emp_Master.Emp_Name' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
Is there any solution for this?
you use either the subquery you found yourself:
select Emp_Name, Dept_Name, Emp_Salery
from V_New_Emp_Master
where Emp_Salery = ( select max(Emp_Salery) from V_New_Emp_Master as f where f.Dept_Id = V_New_Emp_Master.Dept_Id);
or go with a top 1 (which would be preferable if V_New_Emp_Master a view which needs some time to execute) :
select top 1
Emp_Name, Dept_Name, Emp_Salery
from V_New_Emp_Master
order by Emp_Salery desc
or if you need maybe the top salary per Dept_Id:
select Emp_Name, Dept_Name, Emp_Salery, Dept_Id
from (
select *
, max(Emp_Salery) over (partition by dept_id) max_Salery
from V_New_Emp_Master
) src
where Emp_Salery=max_Salary
in ms sql server aggregate function queries, you can only include a column in select only if the column itself is included in an aggregate function or if the column is used to group the rows in the group by clause. In your case you will have to structure your query to a complex query with an aggregate function query as a sub query.
something like,
select Emp_Name,Emp_Salery from V_New_Emp_Master where Emp_Salery=(select MAX(Emp_Salery) from V_New_Emp_Master group by Dept_Id Error );
I haven't checked the query but it is definitely something like this, hope this turns you in the right direction.
Related
I have an issue where my database contains a table with these columns:
Program_ID, Vehicle_VIN, Vehicle_Type
I need to create a report where will be:
Program_ID, AmountOfAllPoliciesInProgram, PercentageDuplicatesInProgram
where Vehicle_type = 10
and criteria for the duplicate is to have Vehicle_VIN more than 1 unique time in the table for dedicated Program_ID.
It's in Microsoft SQL Server Management Studio
AmountOfAllPoliciesInProgram is:
SELECT
PROGRAM_ID, COUNT(*) AS AmountOfAllPoliciesInProgram
FROM
dbo.table
WHERE
Vehicle_type = 10
GROUP BY
PROGRAM_ID
I'm not 100% sure I understand you correctly, but you can count distinct Vehicle_VIN and use the having clause to test if the count of distinct Vehicle_VIN is larger than 1. Like so,
SELECT PROGRAM_ID, COUNT(*) as AmountOfAllPoliciesInProgram, count(distinct Vehicle_VIN) as VIN_COUNT
FROM dbo.table
where Vehicle_type = 10
group by PROGRAM_ID
having count(distinct Vehicle_VIN)>1
I'm busy teaching myself SQL Server, using SQL Server Management Studio. Here's the code producing the error:
SELECT SalesPersonID, COUNT(SalesOrderID), YEAR(OrderDate) AS SalesYear
FROM Sales.SalesOrderHeader
GROUP BY SalesYear;
Why does it throw this error?
Invalid column name 'SalesYear'.
Invalid column name 'SalesYear'.
This column will not be there in table SalesOrderHeader
SELECT SalesPersonID, COUNT(SalesOrderID), YEAR(OrderDate) AS SalesYear
FROM Sales.SalesOrderHeader GROUP BY YEAR(OrderDate)
This has to do with logical query processing model..Sales year is called an alias here and as per logical query processing model,below are the operators that are executed in sequence..
1 FROM
2 WHERE
3 GROUP BY
4 HAVING
5 SELECT
5.1 SELECT list
5.2 DISTINCT
6 ORDER BY
7 TOP / OFFSET-FETCH
so ,in above steps ,group by will be executed in 3rd stage and your select will be executed in 5th stage..
This means your alias(which is in select stage) ,will be visible to operators following select (after 5),but not before them..
I would suggest taking a book which teaches basics well and i found Itzik Ben-Gan books to be extremely helpfull T-SQL Fundamentals Third Edition
You can try the following query and test to get your expected result.
DECLARE #SalesOrderHeader TABLE(SalesPersonID INT,SalesOrderID INT,OrderDate DATETIME)
INSERT INTO #SalesOrderHeader
SELECT 1,101,'20-Mar-2018' UNION ALL SELECT 1,102,'21-Mar-2018' UNION ALL SELECT 1,102,'21-Mar-2018' UNION ALL SELECT 2,202,'21-Mar-2018'
SELECT * FROM #SalesOrderHeader
SELECT SalesPersonID AS SalesPersonID, COUNT(SalesOrderID) NoOfOrder, YEAR(OrderDate) AS SalesYear
FROM #SalesOrderHeader
GROUP BY SalesPersonID,YEAR(OrderDate);
Thanks.
How can I perform a subtraction between the results of 2 queries with a group by?
The first query returns the number of all, let's say houses that I can rent out, while the second returns the ones already rented.
SELECT
(SELECT COUNT(*) FROM ... GroupBy ...)
- (SELECT COUNT(*) FROM ... WHERE ...group by) AS Difference
First query result
count() column2 column3
3 studio newYork
6 studio pekin
3 apprtment pekin
5 house london
1 house lagos
Second query result
count() column2 column3
2 studio newYork
I would love to have the first query getting updated depending the the result of the second
count() column2 column3
1 studio newYork
6 studio pekin
3 apprtment pekin
5 house london
1 house lagos
Just use conditional aggregation:
SELECT COUNT(*) -
SUM(CASE WHEN <some_condition> THEN 1 ELSE 0 END) AS some_count,
column2,
column3
FROM yourTable
GROUP BY column2, column3
Here <some_condition> is whatever would have appeared in the WHERE clause of your original second count query.
How can I perform a subtraction between the results of 2 queries with
a group by?
You are close with what you have. There are a few changes that would make this work easier, however:
Alias the results of your two
subqueries. This will make them easier to use.
Return more columns from your subqueries so that you may join on "something" which would allow for subtraction to only occur on matching rows.
Add an alias to your Count(*) statements. Again, this will make them easier to use.
If this image demonstrates what you are looking for:
Then I believe this query will help you out:
SELECT op.ApartmentType,
op.ApartmentLocation,
op.TotalOwned,
ISNULL(tp.TotalOccupied, 0) AS [TotalOccupied],
op.TotalOwned - ISNULL(tp.TotalOccupied,0) AS [TotalVacant]
FROM
(
SELECT *,
COUNT(*) as TotalOwned
FROM SO_SubtractionQuestion.OwnedProperties
GROUP BY ApartmentType, ApartmentLocation
) AS op
LEFT JOIN
(
SELECT *,
COUNT(*) as TotalOccupied
FROM [SO_SubtractionQuestion].[OccupiedProperties]
GROUP BY ApartmentType, ApartmentLocation
) AS tp
ON op.ApartmentType = tp.ApartmentType
AND op.ApartmentLocation = tp.ApartmentLocation
I set this query up similar to your own: it has a select statement with two subqueries and the subqueries have a Count(*) on a grouped query. I also added what I suggested above to it:
My first subquery is aliased with op (owned properties) and my second is aliased with tp(taken properties).
I am returning more columns so that I may properly join them in my outer query.
My Count(*) statements in my subqueries have aliases.
In my outer query, I am then able to join on ApartmentType and ApartmentLocation (look below for the example table/data setup). This creates a result set that is joined on ApartmentType and ApartmentLocation that also contains how many Owned Properties there are (the Count(*) from the first subquery) and how many Occupied Properties there are (the Count(*) from the second subquery). At this point, because I have everything aliased, I am able to do simple subtraction to see how many properties are vacant with op.TotalOwned - ISNULL(tp.TotalOccupied,0) AS [TotalVacant].
I am also using ISNULL to correct for null values. If I did not have this, the result of the subtraction would also be null for rows that did not have a match from the second subquery.
Test Table/Data Setup
To set up the example for yourself, here are the queries to run:
Step 1
For organizational purposes
CREATE SCHEMA SO_SubtractionQuestion;
Step 2
CREATE TABLE SO_SubtractionQuestion.OwnedProperties
(
ApartmentType varchar(20),
ApartmentLocation varchar(20)
);
CREATE TABLE SO_SubtractionQuestion.OccupiedProperties
(
ApartmentType varchar(20),
ApartmentLocation varchar(20)
);
INSERT INTO [SO_SubtractionQuestion].[OwnedProperties] VALUES ('Studio', 'New York'), ('Studio', 'New York'), ('Studio', 'New York'), ('House', 'New York'), ('House', 'Madison');
INSERT INTO [SO_SubtractionQuestion].[OccupiedProperties] VALUES ('Studio', 'New York'), ('Studio', 'New York');
Select Column2, Column3, Count(*)-(Select Count(*)
From Table2
Where Table1.Column2=Table2.Column2 and Table1.Column3=Table2.Column3)
From Table1
Group by Column2, Column3
Environment:
OS: Windows Server 2012 DataCenter
DBMS: SQL Server 2012
Hardware (VPS): Xeon E5530 4 cores + 4GB RAM
Question:
I have a large table with 140 million rows. Some rows are supposed to be duplicate so I want to remove such rows. For example:
id name value timestamp
---------------------------------------
001 dummy1 10 2015-7-27 10:00:00
002 dummy1 10 2015-7-27 10:00:00 <-- duplicate
003 dummy1 20 2015-7-27 10:00:00
The second row is deemed duplicate because it has identical name, value and timestamp regardless of different id with the first row.
Note: the first two rows are duplicate NOT because of all identical columns, but due to self-defined rules.
I tried to remove such duplication by using window function:
select
id, name, value, timestamp
from
(select
id, name, value, timestamp,
DATEDIFF(SECOND, lag(timestamp, 1) over (partition by name order by timestamp),
timestamp) [TimeDiff]
from table) tab
But after an hour of execution, the lock is used up and error was raised:
Msg 1204, Level 19, State 4, Line 2
The instance of the SQL Server Database Engine cannot obtain a LOCK resource at this time. Rerun your statement when there are fewer active users. Ask the database administrator to check the lock and memory configuration for this instance, or to check for long-running transactions.
How could I remove such duplicate rows in an efficient way?
What about using a cte? Something like this.
with DeDupe as
(
select id
, [name]
, [value]
, [timestamp]
, ROW_NUMBER() over (partition by [name], [value], [timestamp] order by id) as RowNum
from SomeTable
)
Delete DeDupe
where RowNum > 1;
If only thing is selection of non-duplicate rows from table, consider using this script
SELECT MIN(id), name, value, timestamp FROM table GROUP BY name, value, timestamp
If you need to delete duplicate rows:
DELETE FROM table WHERE id NOT IN ( SELECT MIN(id) FROM table GROUP BY name, value, timestamp)
or
DELETE t FROM table t INNER JOIN
table t2 ON
t.name=t2.name AND
t.value=t2.value AND
t.timestamp=t2.timestamp AND
t2.id<t.id
Try something like this - determine the lowest ID for each set of values, then delete rows that have an ID other than the lowest one.
Select Name, Value, TimeStamp, min(ID) as LowestID
into #temp1
From MyTable
group by Name, Value, TimeStamp
Delete MyTable
from MyTable a
inner join #temp1 b
on a.Name = b.Name
and a.Value = b.Value
and a.Timestamp = b.timestamp
and a.ID <> b.LowestID
I have two tables in a MS SQL Server database:
Table1
Emp_ID, First_Name, Last_Name
1 Joe Smith
2 Bob Jones
Table2
Emp_ID, Dept_ID, Status
1 1 Active
1 2 NotActive
1 3 NotActive
2 1 Active
What I would like to do is create a SQL select statement that displays a row for every employee and department combination along with the status even if the employee has never been in the department (table 2). For the sample data, this should bring back 6 records since there are 2 employees and 3 departments.
Any help would be appreciated!
Thank you
If you don't have a departments table, you'll need to create a subquery to get the distinct list of dept_ids to cross join on:
select emp_id, first_name, last_name, dept.dept_id, status
from empl
cross join (select distinct dept_id from empdept) dept
left join empdept on empl.emp_id = empdept.empt_id
and dept.dept_id = empdept.dept_id
SQL Fiddle Demo
SELECT *
FROM table1 T1 FULL OUTER JOIN table2 T2
ON T1.EMP_ID=T2.EMP_ID