SQL: Consolidating results - sql

I am a relative beginner in SQL (Learned and forgotten many times) and entirely self taught so please excuse my likely lack of proper terminology. I made a query that pulls items that have been returned, each items' row has a return code. Here is a result sample:
In the final report(Created with Visual Studio), I would like to be able to have a count of returns by return type but I would need to consolidate the 40 or so return codes into 4 or 5 return type groups. So RET_CODE values ) and . are both product quality issues and would count in the "Product Quality" row.
I could use some help with what the best way to accomplish this would be.
Thank You
Andrew

The bad way!
You could do this by creating the grouping within your SQL statement with something like
SELECT
*,
CASE
WHEN RET_CODE IN ('.', ')') THEN 'Quality Error'
WHEN RET_CODE IN ('X', 'Y', 'Z') THEN 'Some Other error'
ELSE [Desc1]
END AS GroupDescription
FROM myTable
The problem with this approach is that you have to keep repeating it every time you want to something similar.
The better option. (but not perfect!)
Assuming you do not already have such a table...
Create a table that contains the grouping. You can use this in the future whenever you need to do this kind of thing.
For example.
CREATE TABLE dbo.MyErrorGroupTable (RET_CODE varchar(10), GroupDescription varchar(50))
INSERT INTO dbo.MyErrorGroupTable VALUES
('.', 'Quality Error'),
(')', 'Quality Error'),
('X', 'Some Other Error'),
('Y', 'Some Other Error'),
('.', 'Some Other Error'),
('P', 'UPS Error'),
('A', 'PAck/Pick Error')
etc....
Then you can simply join to this table and use the GroupDescription in your report
e.g.
SELECT
a.*, b.GroupDescription
FROM myTable a
JOIN MyErrorGroupTable b ON a.RET_CODE = b.RET_CODE
Hope this helps...

You're looking for the GROUP BY clause.

Related

How can I avoid "stringly typed" code in T-SQL?

Consider some code like
SELECT
CASE
WHEN [DECISION-MAKER] = 'COKE' THEN 'GIVE COKE'
WHEN [DECISION-MAKER] IN ('PEPSI', 'BLOOD') THEN 'GIVE DEATH'
END AS [EMPLOYEE-ASSIGNMENT],
CASE [DECISION-MAKER]
WHEN 'COKE' THEN 'Employee prefers coke. Give coke.'
WHEN 'PEPSI' THEN 'Employee prefers pepsi. Give death.'
WHEN 'BLOOD' THEN 'Employee is some sort of vampire. Give death.'
END AS [ASSIGNMENT-REASON]
FROM
(
SELECT *,
CASE
WHEN [COMPLEX-LOGIC-1] THEN 'COKE'
WHEN [COMPLEX-LOGIC-2] THEN 'PEPSI'
WHEN [COMPLEX-LOGIC-3] THEN 'BLOOD'
END AS [DECISION-MAKER]
FROM [WHEREVER]
)
I believe that the technical term for such poor code is "stringly typed". The key issue in the above code is that decisions are being made based on a string output that the developer needs to type and consistently get correct. If anything goes wrong, the language will be incapable of throwing errors. In a traditional language, the workaround would be to construct some sort of dictionary to handle these cases. What is the idiomatic solution in T-SQL? I don't like the idea of making a use-once table, but maybe a temp table would be helpful?
I wouldn't worry about having a "Use in one place" table. If you still worry about it cluttering up your database, you can use a table variable.
DECLARE #AssignmentAndReason AS TABLE (
DECISION-MAKER varchar,
EMPLOYEE-ASSIGNMENT varchar,
ASSIGNMENT-REASON varchar
);
INSERT INTO #AssignmentAndReason VALUES
('COKE', 'GIVE COKE', 'Employee prefers coke. Give coke.'),
('PEPSI', 'GIVE DEATH', 'Employee prefers pepsi. Give death.'),
('BLOOD', 'GIVE DEATH', 'Employee is some sort of vampire. Give death.');
SELECT [EMPLOYEE-ASSIGNMENT], [ASSIGNMENT-REASON],
FROM [WHEREVER]
JOIN #AssignmentAndReason ON [DECISION-MAKER] = CASE
WHEN [COMPLEX-LOGIC-1] THEN 'COKE'
WHEN [COMPLEX-LOGIC-2] THEN 'PEPSI'
WHEN [COMPLEX-LOGIC-3] THEN 'BLOOD'
END
uses "with as(query)"
with firstLogic as
(
select PersonID, Name,
CASE
WHEN valueDRINK=1 or valueDRINK=2 THEN 'COKE'
WHEN valueDRINK=3 or valueDRINK=4 THEN 'PEPSI'
WHEN valueDRINK=5 THEN 'BLOOD'
END AS [DECISION-MAKER]
from Persons
where country='co'
)
select PersonID, Name ,[DECISION-MAKER],
CASE
WHEN [DECISION-MAKER] = 'COKE' THEN 'GIVE COKE'
WHEN [DECISION-MAKER] IN ('PEPSI', 'BLOOD') THEN 'GIVE DEATH'
END AS [EMPLOYEE-ASSIGNMENT],
CASE [DECISION-MAKER]
WHEN 'COKE' THEN 'Employee prefers coke. Give coke.'
WHEN 'PEPSI' THEN 'Employee prefers pepsi. Give death.'
WHEN 'BLOOD' THEN 'Employee is some sort of vampire. Give death.'
END AS [ASSIGNMENT-REASON]
from firstLogic
"with" allows you to have different queries and then join them without creating a temporary table
you can see it in this example

Decode function in oracle for null values

I am working on a java code in which i am comparing the user input values with database values.
I am writing the code to display the alert message to the users on selection of particular division from drop down menu. But there are some alert message which I want to display to all users of every division.
I have the table columns as sr_n0, alert_desc, div_code, alert_flag.
Initially I am checking the div_code = 'division code' and alert_flag = 'y' to display division specific alert message.
But now I want to know how the decode function will work if div_code = null and alert_flag = 'y'.
I have tried this SQL query :
SELECT DECODE(DIV_CODE,'61','Division A',
'62','Division B',
'ALL')
FROM ALERTS WHERE ALERT_FLAG='Y';
If there is no match, then the result will be 'ALL'. I would strongly encourage you to use the ANSI-standard CASE statement, instead of the Oracle-specific DECODE() function:
SELECT (CASE DIV_CODE
WHEN '61' THEN 'Division A'
WHEN '62' THEN 'Division B'
ELSE 'ALL'
END)
FROM ALERTS
WHERE ALERT_FLAG = 'Y';
I solved this issue by writing simple SQL command and it worked for me.
SELECT ALERT_DESC FROM ALERTS A
WHERE
A.DIV_CODE IS NULL
AND A.ALERT_FLAG='Y' ;

SQL server query on json string for stats

I have this SQL Server database that holds contest participations. In the Participation table, I have various fields and a special one called ParticipationDetails. It's a varchar(MAX). This field is used to throw in all contest specific data in json format. Example rows:
Id,ParticipationDetails
1,"{'Phone evening': '6546546541', 'Store': 'StoreABC', 'Math': '2', 'Age': '01/01/1951'}"
2,"{'Phone evening': '6546546542', 'Store': 'StoreABC', 'Math': '2', 'Age': '01/01/1952'}"
3,"{'Phone evening': '6546546543', 'Store': 'StoreXYZ', 'Math': '2', 'Age': '01/01/1953'}"
4,"{'Phone evening': '6546546544', 'Store': 'StoreABC', 'Math': '3', 'Age': '01/01/1954'}"
I'm trying to get a a query runing, that will yield this result:
Store, Count
StoreABC, 3
StoreXYZ, 1
I used to run this query:
SELECT TOP (20) ParticipationDetails, COUNT(*) Count FROM Participation GROUP BY ParticipationDetails ORDER BY Count DESC
This works as long as I want unique ParticipationDetails. How can I change this to "sub-query" into my json strings. I've gotten to this query, but I'm kind of stuck here:
SELECT 'StoreABC' Store, Count(*) Count FROM Participation WHERE ParticipationDetails LIKE '%StoreABC%'
This query gets me the results I want for a specific store, but I want the store value to be "anything that was put in there".
Thanks for the help!
first of all, I suggest to avoid any json management with t-sql, since is not natively supported. If you have an application layer, let it to manage those kind of formatted data (i.e. .net framework and non MS frameworks have json serializers available).
However, you can convert your json strings using the function described in this link.
You can also write your own query which works with strings. Something like the following one:
SELECT
T.Store,
COUNT(*) AS [Count]
FROM
(
SELECT
STUFF(
STUFF(ParticipationDetails, 1, CHARINDEX('"Store"', ParticipationDetails) + 9, ''),
CHARINDEX('"Math"',
STUFF(ParticipationDetails, 1, CHARINDEX('"Store"', ParticipationDetails) + 9, '')) - 3, LEN(STUFF(ParticipationDetails, 1, CHARINDEX('"Store"', ParticipationDetails) + 9, '')), '')
AS Store
FROM
Participation
) AS T
GROUP BY
T.Store

IQueryDescription SQL Query Returning Limited Records

I created a SQL query that is working in SQL Management Studio, but as soon as I transfer the query into ArcMap's IQueryDescription to try and run it with a User Form, the results that I'm getting back are very limited and there is no clear pattern to the results it is returning. (409 records vs. 15 records)
I am even copying and pasting the query that works into the ArcObjects code, but I get a limited number of records back and no errors are thrown.
Has anyone run into this? What direction should I look for a solution?
I included the query below, although the query itself works just fine in SQL Management Studio.
SELECT CADDATA.CALLINDEX.NCALLHIST2, CADDATA.CALLINDEX.NHISTSEQUENCE, CADDATA.CALLINDEX.SZCALL, CADDATA.CALLINDEX.SZCALLTYPE, CADDATA.CALLINDEX.SZCALLDESC, CADDATA.CALLINDEX.SZGEOGROUP, CADDATA.CALLINDEX.SZPRIORITY, CADDATA.CALLINDEX.SZDISPOSITION, CADDATA.CALLINDEX.LTCREATED, CADDATA.CALLINDEX.LTENTERED, CADDATA.CALLINDEX.LTDISPATCHED, CADDATA.CALLINDEX.LTENROUTE, CADDATA.CALLINDEX.LTONSCENE, CASE WHEN RIGHT(SZLOCATION, CHARINDEX(',', SZLOCATION)) = '' THEN SZLOCATION ELSE LEFT(SZLOCATION, CHARINDEX(',', SZLOCATION) - 1) END AS Location, cast(LTCREATED as date) as gedatedidid FROM CADDATA.CALLINDEX INNER JOIN CADDATA.CALLINDEX_MXSEQUNCE ON CADDATA.CALLINDEX.NCALLHIST1 = CADDATA.CALLINDEX_MXSEQUNCE.NCALLHIST1 AND CADDATA.CALLINDEX.NCALLHIST2 = CADDATA.CALLINDEX_MXSEQUNCE.NCALLHIST2 AND CADDATA.CALLINDEX.NHISTSEQUENCE = CADDATA.CALLINDEX_MXSEQUNCE.NHISTSEQUENCE WHERE (CADDATA.CALLINDEX.SZCALLTYPE IN ('1818', '1825', 'AH', 'BC', 'BS', 'BUS', 'CH', 'F', 'FP', 'PAT', 'PC', 'PW', 'SUB', 'TL', 'TS', 'TST', 'VHC', 'VP')) AND (CADDATA.CALLINDEX.SZGEOGROUP IN ('D1', 'D2', 'D3')) AND (cast(LTCREATED as date) >= '2013-6-4') AND (cast(LTCREATED as date) <= '2013-6-4')

SQL Server 2005 Issue Column name or number of supplied values does not match table definition

I wish to DELETE the data from a table before performing an INSERT INTO, however I keep recieving an error stating:
Insert Error: Column name or number of supplied values does not match table definition.
I've also tried defining the columns the data should be entered into as part of the INSERT INTO statement, but then get issues with column names, even though they are correct. I have a feeling the issues relates to me selecting 2 PostCode entries and converting them into 1, but if someone could shed light on this it would be a big help.
My code can be found below, if you want me to add the code where I was sepcifing column names let me know. So you know the fields selected are all the fields in the Course table other than AutoNum which is a auto number primary key and SSMA_TimeStamp, which is a TimeStamp.
BEGIN
DELETE dbo.Course
INSERT INTO dbo.Course
SELECT
RTRIM( CAST (sd.[RefNo] AS nvarchar(50))) AS 'Student Ref No',
sd.[FirstForeName] AS Forename,
sd.[Surname],
sd.[Address1],
sd.[Address2],
sd.[Address3],
sd.[Address4],
sd.[DateOfBirth] AS DOB,
sd.[PostCodeOut] + ' ' + sd.[PostCodeIn] AS 'Post Code',
o.[Name] AS 'Course Name',
o.[Code] As 'Course Code',
e.[StartDate] AS 'Start Date',
e.[ExpectedGLH] AS 'Exp GLH',
e.[ExpectedEndDate] AS 'Expected End Date',
e.[ActualEndDate] AS 'Actual End Date',
e.[Grade] AS 'Grade',
ou.[Description] AS Outcome,
cs.[Description] AS 'Completion Status',
sd.[Tel1] AS 'Tel 1'
FROM [xxxxxxx].[xxxxxx].[dbo].[StudentDetail] sd
INNER JOIN [xxxxxxx].[xxxxxx].[dbo].[Enrolment] e
ON sd.[StudentDetailID] = e.[StudentDetailID]
Inner JOIN [xxxxxxx].[xxxxxx].[dbo].[Offering] o
ON o.[OfferingID] = e.[OfferingID]
INNER JOIN [xxxxxxx].[xxxxxx].[dbo].[CompletionStatus] cs
ON cs.[CompletionStatusID] = e.[CompletionStatusID]
INNER JOIN [xxxxxxx].[xxxxxx].[dbo].[Outcome] ou
ON ou.[OutcomeID] = e.[OutcomeID]
WHERE sd.[AcademicYearID] = '09/10'
AND
o.[Code] LIKE '%-ee%'
AND
o.[Name] LIKE '%-%dl%'
ORDER BY
sd.[RefNo]
It sounds like your 'Course' table does not match your insert statement, either in the number or names of the columns specified (as per the error message).
Could you add the create table code for the 'Course' table as that will show where the discrepancy lies.
Thanks.
I would explicitly list the columns in the course table that you are inserting into - this may solve your problem/help find your issue, but also reduce maintenance problems in the future.
To fix this issue you need explicitly specify list of the table's columns in the INSERT INTO statement.
you should add a list of columns to the INSERT statement, see below, where you explicitly list each column from dbo.Course that you intend to populate in your INSERT:
INSERT INTO dbo.Course
---<<<<<
(col1, col2, col3, col4, clo5....) ---<<<<<Add this here
---<<<<<
SELECT
RTRIM( CAST (sd.[RefNo] AS nvarchar(50))) AS 'Student Ref No',
sd.[FirstForeName] AS Forename,
sd.[Surname],
sd.[Address1],
sd.[Address2],
sd.[Address3],
sd.[Address4],
sd.[DateOfBirth] AS DOB,
sd.[PostCodeOut] + ' ' + sd.[PostCodeIn] AS 'Post Code',
o.[Name] AS 'Course Name',
o.[Code] As 'Course Code',
e.[StartDate] AS 'Start Date',
e.[ExpectedGLH] AS 'Exp GLH',
e.[ExpectedEndDate] AS 'Expected End Date',
e.[ActualEndDate] AS 'Actual End Date',
e.[Grade] AS 'Grade',
ou.[Description] AS Outcome,
cs.[Description] AS 'Completion Status',
sd.[Tel1] AS 'Tel 1'
FROM ....
then make sure that each column in the SELECT list matches each of these columns and in order. From your error, it sounds like you have too many any or too few returned columns in the SELECT.