I have a scenario where I am working on SQL Server Reporting Services for creating a tablular report and stuck at a point where I get duplicate values for one column. Below is the sample output from the code:
AppID EmpID EmpName
2002912 81555 NULL
2002912 81588 Jenn - 81588
2026880 9328 NULL
2026880 9628 Brad - 09628
2027065 92174 Julie - 92174
2027065 92714 NULL
2028989 72138 NULL
2028989 91366 Alan - 91366
2029233 17438 NULL
2029233 53712 Brad - 53712
2031585 37902 NULL
2031588 17723 Richard - 17723
2031591 54551 Paula - 54551
2031593 52240 Sarah - 52240
2031597 72778 Daisy - 72778
2031603 12659 NULL
Notice the first coulmn (AppID) has few duplicates and the corresponding column EmpName is either Null or has some value. I want to eliminate all the duplicate AppID's where the EmpName is null.
This could have been straight forward if there were no null values for unique AppID's (Refer to the last row) also I can't hardcode as I am dealing with large number of data.
Also please note, all these three columns are coming from different table and have been LEFT JOIN to AppID table. Please let me know if you require to see the code, I didn't paste it here as it is little complex and though might not be required.
Any kind of help and suggestion is appreciated.Thank you
Use the ROW_NUMBER function in a CTE and then pick the first row. Though if there is more than one EmpName which is NOT NULL you will only get the first one in alphabetical order.
WITH AppAndEmp AS
(
SELECT
AppID
, EmpID
, EmpName
, ROW_NUMBER() OVER(PARTITION BY AppId
ORDER BY (CASE WHEN EmpName IS NULL THEN 0 ELSE 1 END) DESC
, EmpName) AS EmpOrder
FROM
dbo.App
LEFT JOIN dbo.Emp
ON App.AppId = Emp.AppId
)
SELECT
*
FROM
AppAndEmp
WHERE
EmpOrder = 1
EDIT
#djphatic: Thanks to your comment. I corrected my answer.
-- These are those who have set a EmpName but have an invalid row too
select * from data where AppID in (
select AppID from data group by AppID having count(AppID) > 1
)
and empname is not null
union
-- These are those who MIGHT have set a EmpName or NULL
select * from data where AppID in (
select AppID from data group by AppID having count(AppID) = 1
)
=> SQLFiddle
For the sake of the failure I leave my previous incorrect answer down here:
You might try this one:
select AppID, min(empid) EmpID, min(EmpName) EmpName
from data
group by AppID
SQLFiddle:
http://sqlfiddle.com/#!3/67cf0/1/0
MIN ignores any null values.
Docs for MIN in SQL Server: http://msdn.microsoft.com/en-us/library/ms179916.aspx
Related
This question is a part of an insert statement in which I am trying to select a value from another value that can be inserted into a column.
For example in my table OnlineServers, I have columns:
ID, ServerID, OnlineSince
In my second table ImportServers, I have columns with the data (The lines after NewYork and Paris are actually empty):
ImportServerName
NewYork
London
Paris
Tokyo
This question is related to SQL Server.
In my third table, which is a look-up table called ServerLookup, I have these columns with data:
ID, ServerName
0 Not specified
1 NewYork
2 London
3 Tokyo
4 Munich
5 Salzburg
Question: I want to have an sql statement which can select ID '0' from ServerLookup table if the value of the column ImportServerName is empty.
What I have so far is:
insert into OnlineServers (ServerID, OnlineSince)
select
(
select ID
from ServerLookup
where ServerLookup.ServerName = ImportServers.ServerName
or ServerLookup.ServerName = ''
),
GETDATE()
from ImportServers
The problem I am facing is if the server name is matched, it also returns an extra row with empty server name.
How can I fix this problem.
Thanks
PS: Forgive me if there is any typo in the code
INSERT INTO OnlineServers
SELECT CASE ImportServerName
WHEN '' THEN 0
ELSE ID
END AS ServerID, GetDate()
FROM ImportedServers s
LEFT JOIN ServerLookup l on s.ImportedServerName = l.ServerName;
This should do it. You LEFT JOIN so you get every record from ImportedServers and use CASE to get 0 where ImportServerName is blank.
Maybe something like this:
SELECT FIRST(column_name) FROM table_name;
Limiting the return to the first match, also, shoudl teh from not be inside the select brackets?
select FIRST(ID)
from ServerLookup
where ServerLookup.ServerName = ImportServers.ServerName
or ServerLookup.ServerName = ''
from ImportServers)
if i understand your problem correctly try something like this
insert into OnlineServers (ServerID, OnlineSince)
select TOP(1) ID ,GETDATE()
from ServerLookup
inner join ImportServers
on ServerLookup.ServerName = ImportServers.ServerName
Where ServerLookup.ServerName = ''
I am newbie to SQL Server, and I want to select all those who changed their department at least once.
The table structure is:
BusinessEntityID
DepartmentID
ShiftID
StartDate
RateChangeDate
Rate
NationalIDNumber
I have the following code to generate an intermediate table
select distinct
DepartmentID, NationalIDNumber
from
Table
where
NationalIDNumber in (select NationalIDNumber
from Ben_VEmployee
group by NationalIDNumber
having count(NationalIDNumber) > 1)
Output:
DepartmentID NationalIDNumber
-----------------------------
1 112457891
2 112457891
4 24756624
4 895209680
5 24756624
5 895209680
7 259388196
My questions is: how to remove non-duplicate records in the intermediate table as above?
So record "7 - 259388196" should be removed because he did not change department.
Thanks.
Try using group by and comparing the maximum and minimum department. If it changed, then these will be different:
select NationalIDNumber
from Ben_VEmployee
group by NationalIDNumber
having min(DepartmentID) <> max(DepartmentID);
If you need the actual departments, you can join this back in to the original data.
If you want a list of every ID number that has been in more than one department, you can use
SELECT COUNT(DepartmentID) AS noDepartments
, NationalIDNumber
FROM Table
GROUP BY NationalIDNumber
HAVING COUNT(DepartmentID) > 1
If you want to delete the records for the deparment the employee used to be in, but isn't any more, than you'd have to know which department that was to know which record to delete! If you do know this, then say, and we can work it out.
I am having the following issue with my query.
I am trying to import data from multiple tables (Fact_Contact, Quali_Seg, etc…) into one table (Fact_Forecast). This is to predict how many individuals are eligible for a specific offer. The problem I am having is that for some reason, the column Date_ID, which is been pulled from Fact_Contact, when importing has NULL values. I don’t know where these NULL values are coming from as the table Fact_Contact don’t have any NULL values in the column DATE_ID.
This is the section of the query that has the problem,
DECLARE #lastDateID int
SELECT TOP 1 #lastDateID = date_id
FROM Fact_Contact
ORDER BY CREATE_DATE DESC
SELECT date_id, Offers.Segmentation_id, Offers.Offer_Code, Offers.Wave_no,
Offers.cadencevalue,
CASE
WHEN dailydata.activity_count IS NOT NULL THEN dailydata.activity_count
ELSE 0
END as "activity_count"
FROM (
SELECT s.Segmentation_id, s.Offer_Code, s.Wave_no, o.cadencevalue,
o.campaign_id, o.offer_desc
FROM Forecast_Model.dbo.Quali_Segment s
LEFT JOIN Forecast_Model.dbo.Dim_Offers o
ON s.offer_code = o.offer_code
) Offers
LEFT JOIN (
SELECT date_id, Offer_Code_1 Offer_Code,
segmentation_group_id, Count(indv_role_id) Activity_count
FROM Forecast_Model.dbo.Fact_Contact
WHERE date_id = #lastDateID
GROUP BY offer_code_1,segmentation_group_id,date_id
) DailyData
ON DailyData.offer_code = Offers.offer_code
AND Offers.Segmentation_id = dailydata.segmentation_group_id
ORDER BY Segmentation_id,Wave_no
The column Date_ID as I mentiones gets only 2 dates which is the same as the #LastDateID which is 2014-05-20 but the rest are NULL.
Thank you,
Omar
date_id will be NULL whenever you have records in Offers (join Quali_Segment) but no matching records in Fact_Contact
I have a table AoObject with a column DisplayName. In name are values like Joe Smith, John Smith, Jane Smith. This goes on for thousands of records.
I want to update the table so that starting with record one up to the last record the value of DisplayName is like this. Joe Smith = Customer1, John Smith = Customer2, Jane Smith = Customer3... and so on until all the name columns sequentially say Customer with a number appended to it and not the current value of the column.
This is SQL Server 2012
***The examples below don't work and I've amended my question. My fault for not including enough details. The table is called Aoobject. The field that needs to be changed is actually called DisplayName. I need to filter the result set with something like the following.
Where ObjectDescription in ('Portfolio Description', 'Portfolio Group Description')
This seems like a bad idea -- the "customer number" should be put into a separate column. It is not part of the name. However, it is easy to do:
with toupdate as (
select t.*, row_number() over (order by recordnum) as seqnum
from table t
)
update toupdate
set fullname = fullname + ' Customer' + cast(seqnum as varchar(255));
I am assuming that you have some numbering for the records (recordnum) because the question says "with record one up to the last record".
EDIT:
If you want the names to be unique, then append a number only for duplicate names.
with toupdate as (
select t.*,
row_number() over (partition by fullname order by recordnum) as fn_seqnum,
count(*) over (partition by fullname) as fn_cnt
from table t
)
update toupdate
set fullname = fullname + ':' + cast(fn_seqnum as varchar(255));
where fn_cnt > 1;
This appends a unique number only when it needs to (for fullnames that have duplicates). And, it keeps the cardinality of the number as low as possible, so only one digit should suffice for the suffix.
Something like this will do.
Hope the Customer name is unique.
;WITH cte_emp AS
(
SELECT CustomerName , ROW_NUMBER() over (order by CustomerName) slno
FROM Customer
)
UPDATE t SET CustomerName = 'Customer ' + cast(slno as varchar)
FROM Customer t
INNER JOIN cte_emp c ON t.CustomerName = c.CustomerName
I have 2 Tables in Ms Access
tbl_Master_Employess
tbl_Emp_Salary
I want to show all the employees in the employee table linked with employee salary table
to link both table the id is coluqEmpID in both table
In the second table, I have a date column. I need a query which should fetch records from both tables using a particular date
I tried the following query:
select coluqEID as EmployeeID , colEName as EmployeeName,"" as Type, "" as Amt
from tbl_Master_Employee
union Select b.coluqEID as EmployeeID, b.colEName as EmployeeName, colType as Type, colAmount as Amt
from tbl_Emp_Salary a, tbl_Master_Employee b
where a.coluqEID = b.coluqEID and a.colDate = #12/09/2013#
However, it shows duplicates.
Query4
EmployeeID EmployeeName Type Amt
1 LAKSHMANAN
1 LAKSHMANAN Advance 100
2 PONRAJ
2 PONRAJ Advance 200
3 VIJAYAN
4 THIRUPATHI
5 VIJAYAKUMAR
6 GOVINDAN
7 TAMILMANI
8 SELVAM
9 ANAMALAI
10 KUMARAN
How would I rewrite my query to avoid duplicates, or what would be a different way to not show duplicates?
The problem with your query is that you are using union when what you want is a join. The union is first going to list all employees with the first part:
select coluqEID as EmployeeID , colEName as EmployeeName,"" as Type, "" as Amt
from tbl_Master_Employee
and then adds to that list all employee records where they have a salary with a certain date.
Select b.coluqEID as EmployeeID, b.colEName as EmployeeName, colType as Type,
colAmount as Amt
from tbl_Emp_Salary a, tbl_Master_Employee b
where a.coluqEID = b.coluqEID and a.colDate = #12/09/2013#
Is your goal to get a list of all employees and only display salary information for those who have a certain date? Some sample data would be useful. Assuming the data here: SQL Fiddle this query should create what you want.
Select a.coluqEID as EmployeeID, colEName as EmployeeName,
b.colType as Type, b.colAmount as Amt
FROM tbl_Master_Employees as a
LEFT JOIN (select coluqEID, colType, colAmount FROM tbl_EMP_Salary
where colDate = '20130912') as b ON a.coluqEID = b.coluqEID;
The first step is to create a select that will get you just the salaries that you want by date. You can then perform a join on this as if you were performing a separate query. You use a LEFT JOIN because you want all of the records from one side, the employees, and only the records that match your criteria from the second side, your salaries.
I believe you will need a join, however as to your question on Unique names.
select **DISTINCT** coluqEID as EmployeeID
Adding the distinct operator would give only uniquely returned results.