SQL Group By Query - sql

I have the following table with one column ArbPlWPos:
+------------+
+ IH-MKE +
+ IH-MKEEA +
+ IH-MKEEB +
+ IH-MKEPE +
+ IH-MKEPM +
+ IH-MVKE1 +
+ IH-MVKM1 +
+------------+
I can run a statement in MS Access which groups by the first 6 letters:
SELECT left(ArbPlWPos, 6), count(left(ArbPlWPos, 6))
FROM my_table
GROUP BY left(ArbPlWPos, 6)
+------------+------+
+ IH-MKE + 10 +
+ IH-MKM + 20 +
+ IH-MVK + 30 +
+------------+------+
How to include the IH-MVK into the IH-MKE, so the result should be:
+------------+------+
+ IH-MKE + 40 +
+ IH-MKM + 20 +
+------------+------+
Is this somehow possible with SQL/Access?

In MS Access, you can do this using a conditional expression, iif():
SELECT iif(ArbPlWPos like "IH-MVK*", "IH-MKE", left(ArbPlWPos, 6)),
count(*)
FROM TABLE
GROUP BY iif(ArbPlWPos like "IH-MVK*", "IH-MKE", left(ArbPlWPos, 6));

You can group by any expression, but you are to repeat it after SELECT (is you need) and after GROUP BY as you did with an usual column. For example:
SELECT my_function_or_expression(column_A, column_B), count(1)
FROM my_table
GROUP BY my_function_or_expression(column_A, column_B);
In your case it will be:
SELECT
CASE WHEN left(ArbPlWPos, 6) = 'IH-MVK'
THEN 'IH-MKE'
ELSE left(ArbPlWPos, 6) END AS cutArbPlWPos,
count(1) AS amount
FROM my_table
GROUP BY CASE WHEN left(ArbPlWPos, 6) = 'IH-MVK'
THEN 'IH-MKE'
ELSE left(ArbPlWPos, 6) END;
You can also simplify it using subquery.
SELECT cutArbPlWPos, count(1)
FROM (SELECT
CASE WHEN left(ArbPlWPos, 6) = 'IH-MVK'
THEN 'IH-MKE'
ELSE left(ArbPlWPos, 6) END AS cutArbPlWPos
FROM my_table
)
GROUP BY cutArbPlWPos;

Related

Ordering SQL SELECT by result of a string comparison

I have a table with two string columns, ID and LANGUAGE. Language can be one of CYM, ENG, GAE.
When selecting data from the table, I want to order it by the language column, putting a specified language at the start of the results, with the other languages later, in any order.
Say I have the data
+===+=====+
+ 1 + CYM +
+ 2 + GAE +
+ 3 + ENG +
+ 4 + CYM +
+===+=====+
and I want the output to be
+===+=====+
+ 3 + ENG +
+ 1 + CYM +
+ 2 + GAE +
+ 4 + CYM +
+===+=====+
How do I do the equivalent of
SELECT ID, LANGUAGE
FROM TABLE
ORDER BY (LANGUAGE = 'ENG'), ID
You can use CASE WHEN to ensure ENG will be first:
SELECT ID, LANGUAGE
FROM your_table
ORDER BY
CASE LANGUAGE WHEN 'ENG' THEN 0
ELSE 1
END ASC;
-- ,ID ASC -- if needed
LiveDemo

Reformatting data in column

have something kinda weird here. I have a database that's called FLDOC. In it has a column called SENTENCE that contains 7 numbers that represent a length of time.
example:
0050000
0750000
0000600
0040615
0000110
In those 7 digits is a length of type since the digits represent YYYMMDD
So what I'd like is a script that can convert it to something like this:
5Y 00M 00D
75Y 00M 00D
6M (or 000Y 6M 00D is fine as well)
4Y 6M 15D etc etc
thanks in advance...
CONCAT is new to SQL Server 2012. If you have previous version of SQL Server, you could do something like this instead to achieve your desired output:
SELECT sentence
,(
CASE
WHEN cast(left(sentence, 3) AS INT) > 0
THEN cast(cast(left(sentence, 3) AS INT) AS VARCHAR(3)) + 'Y '
ELSE cast(left(sentence, 3) AS VARCHAR(3)) + 'Y '
END +
CASE
WHEN cast(substring(sentence, 4, 2) AS INT) > 0
THEN cast(cast(substring(sentence, 4, 2) AS INT) AS VARCHAR(2)) + 'M '
ELSE cast(substring(sentence, 4, 2) AS VARCHAR(2)) + 'M '
END +
CASE
WHEN cast(right(sentence, 2) AS INT) > 0
THEN cast(cast(right(sentence, 2) AS INT) AS VARCHAR(3)) + 'D'
ELSE cast(right(sentence, 2) AS VARCHAR(3)) + 'D'
END
) AS new_sentence
FROM FLDOC;
SQL Fiddle Demo
UPDATE
To answer your question below in the comments, you could maybe just write a update statement like this:
update FLDOC
set sentence = (
CASE
WHEN cast(left(sentence, 3) AS INT) > 0
THEN cast(cast(left(sentence, 3) AS INT) AS VARCHAR(3)) + 'Y '
ELSE cast(left(sentence, 3) AS VARCHAR(3)) + 'Y '
END +
CASE
WHEN cast(substring(sentence, 4, 2) AS INT) > 0
THEN cast(cast(substring(sentence, 4, 2) AS INT) AS VARCHAR(2)) + 'M '
ELSE cast(substring(sentence, 4, 2) AS VARCHAR(2)) + 'M '
END +
CASE
WHEN cast(right(sentence, 2) AS INT) > 0
THEN cast(cast(right(sentence, 2) AS INT) AS VARCHAR(3)) + 'D'
ELSE cast(right(sentence, 2) AS VARCHAR(3)) + 'D'
END
)
Try this query
select convert(varchar(10),left(example,3))+'Y '+
convert(varchar(10),Substring(example,4,3))+'M '+
convert(varchar(10),Right(example,3))+'D'+ from tablename
You can do this with Concat as well:
Select Concat
(
Left(SENTENCE, 3), 'Y ',
SubString(SENTENCE, 4, 2), 'M ',
Right(SENTENCE, 2), 'D'
)
From Table
To condense the expression as in your example, this can be used as well:
Select Concat
(
Case When (IsNumeric(Left(SENTENCE, 3)) = 1 And Left(SENTENCE, 3) <> '000')
Then Convert(Varchar (3), Convert(Int, Left(SENTENCE, 3))) + 'Y ' End,
Case When (IsNumeric(SubString(SENTENCE, 4, 2)) = 1 And SubString(SENTENCE, 4, 2) <> '00')
Then Convert(Varchar (2), Convert(Int, SubString(SENTENCE, 4, 2))) + 'M ' End,
Case When (IsNumeric(Right(SENTENCE, 2)) = 1 And Right(SENTENCE, 2) <> '00')
Then Convert(Varchar (2), Convert(Int, Right(SENTENCE, 2))) + 'D' End
)
From Table

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?

How to combine two sql queries into one

How can I combine these two SQL statements?
SELECT SUM(hits01 + hits02 + hits03 + hits04 + hits05 + hits06 + hits07 + hits08 + hits09) AS 'AEROwiz'
FROM tbl_2011
WHERE appName='AEROwiz'
SELECT SUM(hits10 + hits11 + hits12) AS 'AEROwiz'
FROM tbl_2010
WHERE appName='AEROwiz'
hits10, hits11 and hits12 exist in both tables.
Use a UNION query - just stuff "UNION" between the two queries:
SELECT SUM(...) AS AEROWiz
FROM ...
UNION
SELECT SUM(...) AS AEROWiz
FROM ...
update
wrap the union in yet another query:
SELECT SUM(AEROWiz)
FROM (
.... unioned queries here
) AS child
SELECT SUM(hits01 + hits02 + hits03 + hits04 + hits05 + hits06 +
hits07 + hits08 + hits09) AS 'AEROwiz'
FROM tbl_2011
WHERE appName='AEROwiz'
UNION ALL
SELECT SUM(hits10 + hits11 + hits12) AS 'AEROwiz'
FROM tbl_2010
WHERE appName='AEROwiz'
Use UNION ALL as it will allow duplicates, and UNION will not put duplicates in the query result. With the SUM() aggregate, I'm guessing there's a good chance of duplication summations, so I'd go with UNION ALL for this one.
You could use two subselects:
SELECT
(
SELECT SUM(hits01 + hits02 + hits03 + hits04 + hits05 + hits06 + hits07 + hits08 + hits09)
FROM tbl_2011
WHERE appName='AEROwiz'
) T1
+
(
SELECT SUM(hits10 + hits11 + hits12)
FROM tbl_2010
WHERE appName='AEROwiz'
) T2
AS AEROwiz
You may also want to consider normalizing your database so that you don't have a table for each year.
SELECT SUM(hits01 + hits02 + hits03 + hits04 + hits05 + hits06 +
hits07 + hits08 + hits09 + t2010.hits10 + t2010.hits11 + t2010.hits12) AS 'AEROwiz'
FROM tbl_2010 t2010
JOIN tbl_2011 t2011 ON t2010.appName = t2011.appName
WHERE t2010.appName='AEROwiz'

transform sql query to oracle

i have to transform some query i´m using in SQL to Oracle code. I´m having a lot of trouble with tis. Does anyone know any Query transformer o something like that?. Can someone translate some part of this code for me?.
This is the code:
SELECT PRUEBA = CASE (SELECT TIMEATT FROM READER WHERE PANELID = DEVID AND READERID =
MACHINE) WHEN '1' THEN 'P10' ELSE 'P20' END
+ '0001'
+ CAST(YEAR(EVENT_TIME_UTC)AS VARCHAR)
+ Right('0' + Convert(VarChar(2), Month(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DAY(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(HOUR,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(MINUTE,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(SECOND,EVENT_TIME_UTC)), 2)
+ CAST(YEAR(EVENT_TIME_UTC)AS VARCHAR)
+ Right('0' + Convert(VarChar(2), Month(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DAY(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(HOUR,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(MINUTE,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(SECOND,EVENT_TIME_UTC)), 2)
+ Right('00000000' + Convert(VarChar(8), CARDNUM), 8)
+ Right('00000000' + Convert(VarChar(8), (SELECT SSNO FROM EMP WHERE ID = EMPID)), 8),
FROM events
WHERE eventid = 0 AND eventid = 0
and machine in (11) AND DEVID IN (1,2)
and CARDNUM <> 0 AND EMPID <> 0
and EVENT_TIME_UTC between '2006-02-16' AND '2007-02-09'
Many thanks for your help, i´ll keep looking.
Try this:
SELECT CASE (SELECT timeatt FROM reader WHERE panelid = devid AND readerid =
machine)
WHEN '1' THEN 'P10'
ELSE 'P20'
END
|| '0001'
|| To_char(event_time_utc, 'RRRRMMDDHH24MISS')
|| To_char(event_time_utc, 'RRRRMMDDHH24MISS')
|| Lpad(cardnum, 8, '0')
|| Lpad((SELECT ssno
FROM emp
WHERE id = empid), 8, '0') AS prueba
FROM events
WHERE eventid = 0
AND eventid = 0
AND machine IN ( 11 )
AND devid IN ( 1, 2 )
AND cardnum <> 0
AND empid <> 0
AND event_time_utc BETWEEN TO_DATE('2006-02-16', 'RRRR-MM-DD') AND TO_DATE('2007-02-09', 'RRRR-MM-DD')
I have recently had to make the same conversion from a life in tSQL to plSQL (oracle). A couple of "gotcha's" in the code you posted:
1) In tSQL the plus sign (for concatenation)+ is replaced in plSQL with double pipe ||
2) Most of the time you need a "Reference Cursor" (REF CURSOR) declared to put your results into like
PROCEDURE DEMO_SELECT_4_SO(
//other parameters followed by//
P_RESULT OUT REF CURSOR)
IS
BEGIN
OPEN P_RESULT FOR
SELECT
//fields///
FROM
a_table
WHERE
//you want..//
OR (as with a scalar result like your query) a single parameter of the correct type, like:
PROCEDURE DEMO_SELECT_4_SO(
//other parameters followed by//
P_RESULT OUT varchar2(60))
IS
BEGIN
SELECT
//concatenated fields///
INTO
P_RESULT
FROM
a_table
WHERE
//you want..//
NOTICE That select into in plSQL assigns the selected value to the target parameter and does not create a table as it would in tSQL
3) RIGHT (or LEFT) are SUBSTR functions in plSQL
I have found a lot of utility out of this link http://www.techonthenet.com/oracle/index.php for clear explanations of plSQL.