Using Aggregate and Max functions - sql

I'm having problems with the below query, working in SQL Server.
SELECT
emp_id= CASE employee_id
WHEN ''
THEN RTRIM(last_name) + '_' + RTRIM(first_name)
+ '_' + RTRIM(gender) + '_'
+ RTRIM(race_ethnicity_code) + '_'
+ RTRIM(high_degree_code) + '_' + RTRIM(position_code) + '_'
+ RTRIM(assignment_code)
ELSE employee_id
END ,
last_name, first_name,
assign_perc,
assignment_num,
CAST((total_salary)AS NUMERIC (18,2))* CAST((assign_perc) AS NUMERIC (18,2)) AS salary,
total_salary
FROM employee
ORDER BY last_name, first_name, district_name
My script is a simple extraction of columns, creating a unique key through case statement for emp_id when its null. The problem im having is when multiplying the assign_perc with the total_Salary when that person has multiple assignments and taking the max salary when that sales person is only listed once. For example - my expected results:
John Smith is only a part time worker having one assignment being listed only one time, so his assign_perc will be less than 1 but I still need the max salary rather than the aggregate total (assign_perc*total_salary). Thank you for your help.

As noted above, this is excessively messy since you'll need to use the CASE statement to determine the virtual employee_id. It would be much simpler if you can either refactor this CASE statement into a udf, or store the result in the table for goodness sake!
To clarify what this is going to do - you want to join the employee table on a table containing counts for each employee. The count table would look like this:
SELECT employee_id, COUNT(*) AS employee_count
FROM employee
GROUP BY employee_id
Joining them together would look like this:
SELECT ...
FROM employee
JOIN (SELECT employee_id, COUNT(*) AS employee_count
FROM employee
GROUP BY employee_id) ec
ON employee.employee_id = ec.employee_id
Your calculated salary would now become:
CASE
WHEN ec.employee_count > 1
THEN CAST((total_salary)AS NUMERIC (18,2))* CAST((assign_perc) AS NUMERIC (18,2))
ELSE total_salary
END AS salary,
And here is the complete query substituting the monstrous CASE statement in place of 'employee_id':
SELECT
CASE employee.employee_id
WHEN ''
THEN RTRIM(last_name) + '_' + RTRIM(first_name)
+ '_' + RTRIM(gender) + '_'
+ RTRIM(race_ethnicity_code) + '_'
+ RTRIM(high_degree_code) + '_' + RTRIM(position_code) + '_'
+ RTRIM(assignment_code)
ELSE employee.employee_id
END AS emp_id,
last_name, first_name,
assign_perc,
assignment_num,
CASE
WHEN ec.employee_count > 1
THEN CAST((total_salary)AS NUMERIC (18,2))* CAST((assign_perc) AS NUMERIC (18,2))
ELSE total_salary
END AS salary,
total_salary
FROM employee
JOIN (SELECT CASE employee.employee_id
WHEN ''
THEN RTRIM(last_name) + '_' + RTRIM(first_name)
+ '_' + RTRIM(gender) + '_'
+ RTRIM(race_ethnicity_code) + '_'
+ RTRIM(high_degree_code) + '_' + RTRIM(position_code) + '_'
+ RTRIM(assignment_code)
ELSE employee.employee_id
END AS employee_id, COUNT(*) employee_count
FROM employee
GROUP BY CASE employee.employee_id
WHEN ''
THEN RTRIM(last_name) + '_' + RTRIM(first_name)
+ '_' + RTRIM(gender) + '_'
+ RTRIM(race_ethnicity_code) + '_'
+ RTRIM(high_degree_code) + '_' + RTRIM(position_code) + '_'
+ RTRIM(assignment_code)
ELSE employee.employee_id
END) ec
ON CASE employee.employee_id
WHEN ''
THEN RTRIM(last_name) + '_' + RTRIM(first_name)
+ '_' + RTRIM(gender) + '_'
+ RTRIM(race_ethnicity_code) + '_'
+ RTRIM(high_degree_code) + '_' + RTRIM(position_code) + '_'
+ RTRIM(assignment_code)
ELSE employee.employee_id
END = ec.employee_id
ORDER BY last_name, first_name, district_name

Related

I'm having an issue with syntax in a Stored SQL Procedure

I'm trying to add three additional columns to a stored procedure (I don't have a lot of experience in stored procedures), the columns are Family ID, Address, and Phone No. Although I've run the query and confirmed the syntax for my select statement is correct, when I add the statement to the stored proc, I receive the following error: Incorrect syntax near 'capPrograms'(this would be line 14). I know this probably has to do with hoe I'm trying to implement my statement in the procedure to update it, but I'm not quite sure what the issues as I've tried several changes with similar or more extensive errors. Any assistance is appreciated, I've included the block of code I'm working with below:
SELECT capCase.Id AS capCase_Id,
capCase.DateApplied AS capCase_DateApplied,
CASE
WHEN ISNUMERIC(#cases.origCaseYear)=1 THEN CAST(origCaseYear + 2004 AS VARCHAR) + ' - ' + CAST(capCase.IdYear + 2004 AS VARCHAR)
WHEN #cases.maxRolloverYear IS NOT NULL THEN CAST(capCase.IdYear + 2004 AS VARCHAR) + ' - ' + CAST(#cases.MaxRolloverYear + 2004 AS VARCHAR)
ELSE CAST(capCase.IdYear + 2004 AS VARCHAR)
END AS capCase_IdYear,
Person.id as Person_id,
Person.LastName + ', ' + Person.FirstName AS PersonPrint_Name,
person.idFamily AS Family_ID, person.homePhone AS Phone_No, (SELECT family.physicalAddress1+ ', ' + family. physicalAddressCity+ ' ' +family. physicalAddressZip) AS Address
FROM Family
LEFT JOIN person ON family.Id = person.idFamily;
capPrograms.Program AS capPrograms_Program,
capStatus.Status AS capStatus_Status,
#lastFollowup.followupDate AS capCaseFollowup_Date,
CASE
WHEN capCase.IdCaseWorker IS NULL THEN 'No Worker Assigned'
ELSE caseWorker.LastName + ', ' + caseWorker.FirstName + ISNULL('<' + caseWorker.EmailWork + '>', '')
END AS capCase_IdCaseWorker,
capcaseDenialReason.reason AS capCase_idDenialReason,
Too long to comment, so I added a bunch of comments in your code. You have, A LOT of issues.
SELECT
capCase.Id AS capCase_Id,
capCase.DateApplied AS capCase_DateApplied,
CASE
--here you are referencing a temp table, which isn't joined below
WHEN ISNUMERIC(#cases.origCaseYear)=1 THEN CAST(origCaseYear + 2004 AS VARCHAR) + ' - ' + CAST(capCase.IdYear + 2004 AS VARCHAR)
WHEN #cases.maxRolloverYear IS NOT NULL THEN CAST(capCase.IdYear + 2004 AS VARCHAR) + ' - ' + CAST(#cases.MaxRolloverYear + 2004 AS VARCHAR)
ELSE CAST(capCase.IdYear + 2004 AS VARCHAR)
END AS capCase_IdYear,
Person.id as Person_id,
Person.LastName + ', ' + Person.FirstName AS PersonPrint_Name,
person.idFamily AS Family_ID,
person.homePhone AS Phone_No,
--this subquery as no from clause... that's an issue... you probably want to remove it completly and replace it with the one below
(SELECT family.physicalAddress1+ ', ' + family. physicalAddressCity+ ' ' +family. physicalAddressZip) AS Address,
--this is likely what you want
family.physicalAddress1 + ', ' + family. physicalAddressCity + ' ' + family. physicalAddressZip AS AddressCorrected
FROM Family
LEFT JOIN person ON
family.Id = person.idFamily; --you have a ; here, which terminates the statement. Everything else below isn't included
--Here you need to join the capPrograms and #lastFollowup table..
--here, you listed some columns, without a table reference. You need to join the table above, and move these columns above the FROM clause
capPrograms.Program AS capPrograms_Program,
capStatus.Status AS capStatus_Status,
#lastFollowup.followupDate AS capCaseFollowup_Date,
CASE
WHEN capCase.IdCaseWorker IS NULL THEN 'No Worker Assigned'
ELSE caseWorker.LastName + ', ' + caseWorker.FirstName + ISNULL('<' + caseWorker.EmailWork + '>', '')
END AS capCase_IdCaseWorker,
capcaseDenialReason.reason AS capCase_idDenialReason,

Added a few lines of code and now query is taking 5x as long to run. Executions plans are almost identical

I have a query that has been in production a long time and takes an average of 4 seconds to run. I added the code below which is a declaration of a table and then an insert into that table. then the select query joins to that and returns 1 field from it in the select statement. Now the query takes up to 25 seconds to run.
DECLARE #tmpStageLoc TABLE
(
LP VARCHAR(20) ,
stgloc VARCHAR(20)
)
INSERT INTO #tmpStageLoc
EXEC dbo.spGetStageLoc #ActLP = #LP;
--Try to get data from DW tables first.
INSERT INTO [COMMON_INFORMATION].[dbo].[ProcTmpData]
( SPID ,
DataSetName ,
IntValue1 , --JRB004
ChValue1 , --JRB001
String1 ,
InsDate
)
SELECT DISTINCT
##SPID ,
#datasetname ,
ls.ToDC ,
col.Cust_No --JRB001
,
REPLACE(#LOADNUM, ' ', '') + --JRB007
'~' + 'N/A'
+ --JRB005 Wave number no longer printed on label
'~' + CASE WHEN la.stage_loc IS NULL THEN ''
ELSE la.stage_loc + '-' + ISNULL(la.misc_info,
'')
END + '~' + fa.OrderControlNo + '~' + col.Cust_No
+ '~' + SUBSTRING(cst.name, 1, 20) + '~'
+ SUBSTRING(cst.name, 21, 5) + '~' + LEFT(cst.address1
+ ', '
+ CASE
WHEN cst.address2 IS NULL
THEN ''
ELSE ( cst.address2
+ ', ' )
END + cst.city
+ ', '
+ cst.state, 45)
+ '~' + ls.StopNO + '~' + ls.LoadNo + '~' + e.first_name
+ ' ' + e.last_name + --JRB009
'~' + --JRB009
CASE WHEN cst.plt_usage IS NULL --JRB009
THEN '' --JRB009
ELSE --JRB009
'# ' + LEFT(cst.plt_usage, 20) --JRB009
END + '~' + ISNULL(STG.STGLOC, '') + '~' --JRB009
,
#RUNDTE
FROM dbo.tblFactAction AS fa
LEFT OUTER JOIN COMMON_INFORMATION.dbo.LoadStop AS ls ON LEFT(fa.OrderControlNo,
8) = ls.ExtOrderNo
AND ls.LatestLoadFlg = 1 --JRB008
LEFT OUTER JOIN dbo.RP_LaneAssign AS la ON ls.LoadNo = la.carrier_move_id
OR ls.ExtOrderNo = la.order_num
LEFT OUTER JOIN dbo.Cust_Order_Lookup AS col ON fa.OrderControlNo = col.Order_Control_no
LEFT OUTER JOIN COMMON_INFORMATION.dbo.Partners AS cst ON col.Cust_No = cst.partner_shipto
LEFT OUTER JOIN COMMON_INFORMATION.dbo.Employee AS e ON fa.EmployeeID = CAST(e.emp_no AS VARCHAR(40))
LEFT OUTER JOIN #tmpStageLoc STG ON fa.actlp = STG.LP
WHERE fa.ActLP = #LOADNUM
AND fa.AssignTypeID IN ( 'PB01', 'PF01' )
I have looked at the execution plans in SQL Sentry Plan Explorer and they look almost identical. I am using the free version of the software. I am at a loss at why the query takes so long to run. just an FYI when I execute the stored procedure that is being called it runs instantly.
Any ideas on how I can figure out why the query now runs for so long?

case and concatenation, sql

Im using a SQL server database and im having a hard time with my case statement. What I'm trying to do is insert a concatenation of attributes into an id field (state_issue_teacher_id) when it equals '' (empty field). The problem is that I have some empty id fields that I need to fill with a unique id that is created by a concatenation of attributes through the case statement.
The empty rows above I need to fill with a concatenation of last_name+first_name+gender+race_ethnicity_code+high_degree_code+position_code+assignment_code.
Here is what I have so far:
SELECT
state_issue_teacher_id,
region_code
+ county_code
+ district_code AS district_code ,
last_name ,
first_name ,
assigned_fte = CASE assign_fte
WHEN '' THEN 0
ELSE CAST(assign_fte AS NUMERIC(18,
2))
END ,
CASE WHEN state_issue_teacher_id = '' THEN
RTRIM([last_name]) + '_' + RTRIM([first_name]) + '_' + RTRIM([gender])
+ '_' + RTRIM([race_ethnicity_code]) + '_' + high_degree_code + '_'
+ position_code + '_' + assignment_code
ELSE state_issue_teacher_id
END,
year_time
FROM dbo.example
When concatenating like that you need to account for two possible problems.
First are all of the fields you are concatenating together varchar (or nvarchar) or are some of them int or numeric? If your datatypes are not varchar or nvarchar, then you need to convert them to use them in a concatentation.
The next possible problem is if one or more of the values can be null. You will need to coalesce any value that could be null with a varchar value (usually a space or empty string for a concatenations although sometimes the value "unknown" works too)) or the concatenation will return null as null concatenated with anything else is null.
SELECT
state_issue_teacher_id,
region_code
+ county_code
+ district_code AS district_code ,
last_name ,
first_name ,
assigned_fte = CASE assign_fte
WHEN '' THEN 0
ELSE CAST(assign_fte AS NUMERIC(18,
2))
END ,
CASE WHEN state_issue_teacher_id = '' THEN
RTRIM(coalesce([last_name],'ValueYouUseInsteadOfNull')) + '_' +
RTRIM(coalesce([first_name],'ValueYouUseInsteadOfNull')) + '_' +
RTRIM(coalesce([gender],'ValueYouUseInsteadOfNull')) + '_' +
RTRIM(coalesce([race_ethnicity_code],'ValueYouUseInsteadOfNull')) + '_' +
coalesce(high_degree_code,'ValueYouUseInsteadOfNull') + '_' +
coalesce(position_code,'ValueYouUseInsteadOfNull') + '_' +
coalesce(assignment_code,'ValueYouUseInsteadOfNull')
ELSE state_issue_teacher_id
END,
year_time
FROM dbo.example
Odds are, you have null in some of those fields.
Give this query a try.
Thank you for everyone that answered the question. I got it to work with the below query.
SELECT
state_issue_teacher_id,
region_code
+ county_code
+ district_code AS district_code ,
last_name ,
first_name ,
gender,
race_ethnicity_code,
high_degree_code,
position_code,
assignment_code,
assigned_fte = CASE assign_fte
WHEN '' THEN 0
ELSE CAST(assign_fte AS NUMERIC(18,
2))
END ,
state_issue_teacher_id =
CASE state_issue_teacher_id WHEN '' THEN
RTRIM([last_name]) + '_' + RTRIM([first_name]) + '_' + RTRIM([gender])
+ '_' + RTRIM([race_ethnicity_code]) + '_' + high_degree_code + '_'
+ position_code + '_' + assignment_code
ELSE state_issue_teacher_id
END,
year_time
FROM dbo.example
How about?:
update example
set state_issue_teacher_id =
RTRIM([last_name]) + '_' + RTRIM([first_name]) + '_' + RTRIM([gender])
+ '_' + RTRIM([race_ethnicity_code]) + '_' + high_degree_code + '_'
+ position_code + '_' + assignment_code
WHERE isnull(state_issue_teacher_id, '') = ''

How to join two SQL queries?

Making two SQL queries into the same table
SELECT FirstName,
LastName,
LEFT(FirstName, 1) + '.' + LEFT(LastName, 1) AS Initial
FROM ContactUpdates
This outputs:
FirstName LastName Initial
I want this to join this other one on the right side where Initial ends
SELECT LOWER(LEFT(FirstName, 1) + REPLACE(LastName,'''','' ) )
+ '#email.com' AS Email
FROM ContactUpdates
In the end I want it to be
FirstName LastName Initial Email
But I can't figure out how to make them join any help?
SELECT FirstName,
LastName,
LEFT(FirstName,1) + '.' + LEFT(LastName,1) AS Initial,
LOWER(LEFT(FirstName, 1) + REPLACE(LastName, '''', '')) + '#email.com' AS Email
FROM ContactUpdates
Then simply append that column to the query:
SELECT FirstName
, LastName
, LEFT(FirstName,1) + '.' + LEFT(LastName,1) AS Initial
, LOWER(LEFT(FirstName,1) + REPLACE(LastName,'''','' ) ) + '#email.com' AS Email
FROM ContactUpdates

Grouping by an alias

SELECT COALESCE (rsu.last_name + ', ' + rsu.first_name + ' ' + rsu.middle_name + '.', rsu.last_name + ', ' + rsu.first_name) as student_name, rsu.day_id
FROM roster_school_unattended rsu
GROUP BY student_name
ORDER BY rsu.day_id
does not work. What's the most elegant workaround?
EDIT: The result-set should have something like this
Muster, Hans | 2011-11-01
Muster, Hans | 2011-11-02
Williams, Clay | 2011-10-01
Williams, Clay | 2011-10-02
First the name is grouped by, then for each name there is a sorting of dates.
Doing a subselect would let you avoid having to type it twice:
select t.student_name, t.day_id
from (
select COALESCE (rsu.last_name + ', ' + rsu.first_name + ' ' + rsu.middle_name + '.', rsu.last_name + ', ' + rsu.first_name) as student_name,
rsu.day_id
from roster_school_unattended rsu ) t
group by t.student_name
order by t.day_id
But you've still got a problem with the day_id - it's not included in your grouping clause, so you won't be able to select it without using an aggregate (such as MAX).
You can use a subquery:
select student_name, day_id
from (SELECT COALESCE (rsu.last_name + ', ' + rsu.first_name + ' ' + rsu.middle_name + '.', rsu.last_name + ', ' + rsu.first_name) as student_name, rsu.day_id
FROM roster_school_unattended rsu
) as rows
GROUP BY student_name
ORDER BY day_id
EDIT: Whole thing replaced as the recent edit to the question shows that GROUP BY isn't needed...
Without any changes for 'elegance'...
SELECT
rsu.last_name + ', ' + rsu.first_name + COALESCE (' ' + rsu.middle_name + '.', '') as student_name,
rsu.day_id
FROM
roster_school_unattended AS [rsu]
ORDER BY
rsu.last_name + ', ' + rsu.first_name + COALESCE (' ' + rsu.middle_name + '.', ''),
rsu.day_id
Possible change for 'elegance'...
WITH formatted_rsu AS
(
SELECT rsu.last_name + ', ' + rsu.first_name + COALESCE (' ' + rsu.middle_name + '.', '') as student_name, rsu.day_id
FROM roster_school_unattended AS [rsu]
)
SELECT student_name, day_id
FROM formatted_rus
ORDER BY student_name, day_id
Another possible using APPLY...
SELECT formatted_rsu.student_name, rsu.day_id
FROM roster_school_unattended AS [rsu]
CROSS APPLY (SELECT rsu.last_name + ', ' + rsu.first_name + COALESCE (' ' + rsu.middle_name + '.', '') as student_name) AS [formatted_rsu]
ORDER BY formatted_rsu.student_name, rsu.day_id
I would go with:
SELECT
rsu.last_name
+ ', ' + rsu.first_name
+ COALESCE ( ' ' + rsu.middle_name + '.'
, ''
)
AS student_name
, rsu.day_id
FROM
roster_school_unattended AS rsu
ORDER BY
rsu.last_name
, rsu.first_name
, rsu.middle_name
, rsu.day_id
CROSS APPLY is your friend for aliasing non-windowed expressions:
SELECT this.student_name, MAX(rsu.day_id) AS day_id
FROM roster_school_unattended rsu
CROSS APPLY (
SELECT COALESCE (
rsu.last_name+', '+rsu.first_name+' '+rsu.middle_name+'.'
, rsu.last_name+', '+rsu.first_name
) AS student_name
) this
GROUP BY this.student_name
ORDER BY this.student_name, MAX(rsu.day_id)
(assumes SQL2005 and above).