SQL Server Unique Values - sql-server

I have a SQL Server view that I have created that shows a list of companies and if they have a salesperson assigned, then it will be included, otherwise the value for salesperson will be blank.
When I run the query against this view, for the companies that have a salesperson assigned, I am getting 2 records, 1 with a blank Salesperson and another with the salesperson value.
What I am trying to get is a list with unique values for the company and if they have a salesperson assigned, then it would include that value and if the company doesn't have one, then the salesperson would be left blank.
The first table below shows what my current output is giving me. The 2nd table below shows an example of what I am trying to get. Any help is appreciated.
e.g.
Current Result
CustNO Company SalesPerson
ACM1 Acme Corp
ACM1 Acme Corp Bugs Bunny
ABC1 ABC Company
SSP1 Spacely Sprockets
SSP1 Spacely Sprockets Daffy Duck
SPN1 Springfield Nuclear
SPN1 Springfield Nuclear Porky Pig
Expected Result
CustNO Company SalesPerson
ACM1 Acme Corp Bugs Bunny
ABC1 ABC Company
SSP1 Spacely Sprockets Daffy Duck
SPN1 Springfield Nuclear Porky Pig
Here is the SQL statement for the View, not sure if it helps or not:
Create View SalesList as (
select distinct T1.CUSTNO as 'CustNo',
T1.COMPNAME as 'Company',
T1.SALESCODE as 'SalesID',
T2.EMPLNAME as 'Salesperson',
case
when T2.STATUS = 0 then 'Inactive'
when T2.STATUS = 1 then 'Active'
end as 'SalesStatus',
T2.SALESRATE as 'CommissionPct',
case
when T3.optfield = 'PARTNERAGENT' THEN T3.VALUE
else ''
end as 'AgentCode' ,
case
when T3.OPTFIELD = 'PARTNERAGENT' THEN T4.VDESC
else ''
end as 'AgentName'
from Table1 as T1
left join Table2 as T2 on T1.SALESCODE = T2.SALESCODE
left join Table3 as T3 on T1.CUSTNO = T3.CUSTNO
left join Table4 as T4 on T3.VALUE = T4.VALUE
where T2.EMPLOYEECD = 'PARTNER')
Hopefully this provides more information to be able to provide feedback. Thank you.

Without schema detail it's hard to give you an answer. Based on the screen caps provided I'll assume you're trying to perform aggregation, with non-empty Sales Person returned if any. As a trick, built-in function MAX may help.
SELECT
CustNo, Company, MAX("Sales Person") AS "Sales Person"
FROM
tableA
GROUP BY CustNo, Company

Related

T-SQL - joining a transaction table to an audit table

Say I have these two tables:
Transaction Table
Pmt ID VendorID PaymentDate
1 1 2017-10-01 00:14:42
2 2 2017-09-03 00:08:23
The second table has a list of those VendorIDs, and everytime the associated email changed. It could have changed tons of times.
Audit Table
VendorID Email CreateDateUTC
1 a#gmail.com 2016-01-01 17:51:08
1 b#gmail.com 2016-03-03 12:40:03
1 c#gmail.com 2017-01-10 03:40:04
2 li#gmail.com 2017-03-30 05:40:03
Edit: So say this would show that any payment that went to vendor id 1 after 2016-01-01 17:51:08 but before 2016-03-03 12:40:03 went to a#gmail.com. Any payment that went to vendor id 1 after 2016-03-03 12:40:03 but before 2017-01-10 03:40:04 went to b#gmail.com. And that anything to vendor id 1 that went after 2017-01-10 03:40:04 went to c#gmail.com (unless of course, there's another more recent entry for vendor 1 in the Audit Table).
If I say - wanted to know every transaction that went out to email example#gmail.com, how could I query that?
My assumption is I'd take the transaction table - then join the audit table. Then OK, we have every transaction, and the email it went to. But, how to join only the correct email? Or, am I maybe thinking about this the wrong way entirely?
You Have to create one vendor master in which only main distinct vendor is stored with unique id.
Then create a sub table vendor contact detail.In that add the more than on contact detail for the vendor created in the master and in vendor contact detail also insert one field isPrimary that is bifurcate the Vendor address to be chosen.
then make join and do the task
Need more info, but maybe this will work?
select distinct t.PmtID, t.VendorID, t.PaymentDate
from tblTrans t
inner join tblAudit a
on t.VendorID = a.VendorID
where t.PaymentDate <= a.CreateDateUTC
and a.Email = 'a#gmail.com'
order by t.PaymentDate
The following query returns all rows from transaction table and it matches audit table and gets the email ID to which the email has been sent at the time of transaction
SELECT * FROM
(
SELECT VENDOR.*,Audit.Email,ROW_NUMBER() OVER(PARTITION BY
Vendor.VendorID ORDER BY DATEDIFF(D,CreateDateUTC, PaymentDate) DESC) RNo
FROM Vendor LEFT OUTER JOIN Audit ON Vendor.VendorId =Audit.VendorId
WHERE PaymentDate > CreateDateUTC
)T
WHERE RNo = 1

SQL join conditional either or not both?

I have 3 tables that I'm joining and 2 variables that I'm using in one of the joins.
What I'm trying to do is figure out how to join based on either of the statements but not both.
Here's the current query:
SELECT DISTINCT
WR.Id,
CAL.Id as 'CalendarId',
T.[First Of Month],
T.[Last of Month],
WR.Supervisor,
WR.cd_Manager as [Manager], --Added to search by the Manager--
WR.[Shift] as 'ShiftId'
INTO #Workers
FROM #T T
--Calendar
RIGHT JOIN [dbo].[Calendar] CAL
ON CAL.StartDate <= T.[Last of Month]
AND CAL.EndDate >= T.[First of Month]
--Workers
--This is the problem join
RIGHT JOIN [dbo].[Worker_Filtered]WR
ON WR.Supervisor IN (SELECT Id FROM [dbo].[User] WHERE FullName IN(#Supervisors))
or (WR.Supervisor IN (SELECT Id FROM [dbo].[User] WHERE FullName IN(#Supervisors))
AND WR.cd_Manager IN(SELECT Id FROM [dbo].[User] WHERE FullNameIN(#Manager))) --Added to search by the Manager--
AND WR.[Type] = '333E7907-EB80-4021-8CDB-5380F0EC89FF' --internal
WHERE CAL.Id = WR.Calendar
AND WR.[Shift] IS NOT NULL
What I want to do is either have the result based on the Worker_Filtered table matching the #Supervisor or (but not both) have it matching both the #Supervisor and #Manager.
The way it is now if it matches either condition it will be returned. This should be limiting the returned results to Workers that have both the Supervisor and Manager which would be a smaller data set than if they only match the Supervisor.
UPDATE
The query that I have above is part of a greater whole that pulls data for a supervisor's workers.
I want to also limit it to managers that are under a particular supervisor.
For example, if #Supervisor = John Doe and #Manager = Jane Doe and John has 9 workers 8 of which are under Jane's management then I would expect the end result to show that there are only 8 workers for each month. With the current query, it is still showing all 9 for each month.
If I change part of the RIGHT JOIN to:
WR.Supervisor IN (SELECT Id FROM [dbo].[User] WHERE FullName IN (#Supervisors))
AND WR.cd_Manager IN(SELECT Id FROM [dbo].[User] WHERE FullName IN(#Manager))
Then it just returns 12 rows of NULL.
UPDATE 2
Sorry, this has taken so long to get a sample up. I could not get SQL Fiddle to work for SQL Server 2008/2014 so I am using rextester instead:
Sample
This shows the results as 108 lines. But what I want to show is just the first 96 lines.
UPDATE 3
I have made a slight update to the Sample. this does get the results that I want. I can set #Manager to NULL and it will pull all 108 records, or I can have the correct Manager name in there and it'll only pull those that match both Supervisor and Manager.
However, I'm doing this with an IF ELSE and I was hoping to avoid doing that as it duplicates code for the insert into the Worker table.
The description of expected results in update 3 makes it all clear now, thanks. Your 'problem' join needs to be:
RIGHT JOIN Worker_Filtered wr on (wr.Supervisor in(#Supervisors)
and case when #Manager is null then 1
else case when wr.Manager in(#Manager) then 1 else 0 end
end = 1)
By the way, I don't know what you are expecting the in(#Supervisors) to achieve, but if you're hoping to supply a comma separated list of supervisors as a single string and have wr.Supervisor match any one of them then you're going to be disappointed. This query works exactly the same if you have = #Supervisors instead.

SSRS - Grouping multiple rows per page based on varchar column

I'm trying to create an SSRS report that will display all timesheets per person, per accounting period (month) on a single page. However, I'm stuggling to work out how the result should be grouped. So far all I seem to be able to do is get one line to appear per specified user per page.
My T-SQL looks like this:
SELECT tblADSI.DisplayName AS FullName,
ds.[Date of Work],
ds.Hours,
ds.[Description of Work],
ds.Mileage,
ds.Subsistence,
ds.[Activity Code] AS CompanyRef,
c.[Cost Center] AS DiaryClient,
r.Role,
c.Description AS Project,
ds.[Accounting Period],
ds.[Rechargeable Items]
FROM [Diary Sheets] ds
LEFT JOIN Commissions c on c.[Commission Code] = ds.[Commission Code]
LEFT JOIN dbo.Roles r on r.Commission = ds.[Commission Code] and r.EmployeeID = ds.EmployeeID
LEFT JOIN [Accounting Period] ap ON ap.ID = ds.[Accounting Period ID]
LEFT JOIN (SELECT displayName,
EmployeeID FROM OpenQuery (
ADSI,
'SELECT
displayName,
EmployeeID
FROM ''LDAP://example.domaincontroller.com/OU=Unit1,DC=domaincontroller,DC=com''
WHERE objectCategory = ''person''
AND objectClass = ''User''
') AS tblADSI
UNION
SELECT displayName,
EmployeeID
FROM OpenQuery (
ADSI,
'SELECT
displayName,
EmployeeID
FROM ''example.domaincontroller.com/OU=Unit2,DC=domaincontroller,DC=com''
WHERE objectCategory = ''person''
AND objectClass = ''User''
') AS tblADSI
) AS tblADSI
ON tblADSI.EmployeeID = ds.employeeID
WHERE c.[Commission Code] = 'Example Commission'
AND ap.[Accounting Period] = 'Febuary 2015'
ORDER BY FullName, ds.[Date of Work], ds.[Activity Code]
An example output from the SQL would be.
-- Name Date Of Work Hours
John Smith 01/02/2015 9
John Smith 02/02/2015 10
Jane Doe 01/02/2015 5
Jane Doe 02/02/2015 5
Mike Smith 01/02/2015 8
Mike Smith 02/02/2015 9
So using the SQL above as my example I've built a report which should display per page every user (based on the commission parameter set by the users) within a particular commission. However, all that seems to be happening in the report is it shows one row (the most recent entry for the February accounting period) and nothing more. For example:
-- Name Date Of Work Hours
John Smith 01/02/2015 9
Jane Doe 01/02/2015 5
Mike Smith 01/02/2015 8
I actually need it to show all diary sheets for the accounting period per user so in the report, using John Smith as the example, it would appear as so:
-- Name Date Of Work Hours
John Smith 01/02/2015 9
John Smith 02/02/2015 10
And so on and so forth for every other user on a new page.
Does anybody know how I can achieve this? I've looked into and tried some SSRS grouping (which I suspect is the solution) but I'm completely at a loss. No matter what type of grouping I try it always comes out the same.
I've been writing SQL for a couple of years, but I'm relatively new to SSRS and my SSRS knowledge completely self taught so some of my terminology/formatting is probably incorrect.
I managed to fix it by adding all columns from my SELECT statement as parent row groups on my tablix. Thanks mxix and NickyvV for your suggestions, much appreciated.

SQL Statement to total all employee records

I have a sql statement that is missing all employee names.
Table employee_list contains all employees for the company.
Table apps contain the employee that is assigned to the app
Table details contains the total dollar amount for the order
My query will not group and total for employees that did not have any apps. For example employee John had 5 apps for $250, Bill had 2 apps for $75 and Henry had 0 apps for $0 (no rows in apps or details table for Henry).
My query returns:
John 5 250.00
Bill 2 75.00
I need it to return
John 5 250.00
Bill 2 75.00
Henry 0 0.00
Any ideas? Here is my current code
SELECT employee_list.Fullname,
count(apps.acntnum),
sum(details.cost)
FROM employee_list
left join apps on employee_list.Fullname=apps.EmployeeName
LEFT JOIN details ON (apps.ID=details.ObjOwner_ID AND details.Active=1)
Group BY
employee_list.Fullname
The important thing is to be using a LEFT JOIN from your employee_list table and any subsequent tables you're joining to, and to not do anything that will filter out NULLs from the right-hand tables (because the NULLs would be for the 'missing' rows).
Your query is fine, but I suspect you're using it in a wider query, where you may inadvertently have an INNER JOIN or mention one of the columns in a WHERE clause.
I agree with all the other answers, however, you could also try this....
SELECT employee_list.Fullname,
(SELECT count(apps.acntnum) FROM apps WHERE employee_list.Fullname=apps.EmployeeName) AS Cnt,
(SELECT sum(details.cost) FROM apps LEFT JOIN details ON (apps.ID=details.ObjOwner_ID AND details.Active=1) WHERE employee_list.Fullname=apps.EmployeeName) AS cost
FROM employee_list
This will always return the full list of employees, and separately go and count/sum the other values.
This answer does not take performance into account.

T-SQL How To: Compare and List Duplicate Entries in a Table

SQL Server 2000. Single table has a list of users that includes a unique user ID and a non-unique user name.
I want to search the table and list out any users that share the same non-unique user name. For example, my table looks like this:
ID User Name Name
== ========= ====
0 parker Peter Parker
1 parker Mary Jane Parker
2 heroman Joseph (Joey) Carter Jones
3 thehulk Bruce Banner
What I want to do is do a SELECT and have the result set be:
ID User Name Name
== ========= ====
0 parker Peter Parker
1 parker Mary Jane Parker
from my table.
I'm not a T-SQL guru. I can do the basic joins and such, but I'm thinking there must be an elegant way of doing this. Barring elegance, there must be ANY way of doing this.
I appreciate any methods that you can help me with on this topic. Thanks!
---Dan---
One way
select t1.* from Table t1
join(
select username from Table
group by username
having count(username) >1) t2 on t1.username = t2.username
The simplest way I can think of to do this uses a sub-query:
select * from username un1 where exists
(select null from username un2
where un1.user_name = un2.user_name and un1.id <> un2.id);
The sub-query selects all names that have >1 row with that name... outer query selects all the rows matching those IDs.
SELECT T.*
FROM T
, (SELECT Dupe_candidates.USERNAME
FROM T AS Dupe_candidates
GROUP BY Dupe_candidates.USERNAME
HAVING count(*)>1
) Dupes
WHERE T.USERNAME=Dupes.USERNAME
You can try the following:
SELECT *
FROM dbo.Person as p1
WHERE
(SELECT COUNT(*) FROM dbo.Person AS p2 WHERE p2.UserName = p1.UserName) > 1;

Resources