Ordering SQL SELECT by result of a string comparison - sql

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

Related

querying information from next row

I created this SQL and dont know how to query the next row. We use SQL 2008 so cant use lag/lead
SELECT P_MTN AS MTN
,P_DATE AS DATE
,CONVERT(VARCHAR(50), SEQU) AS NUM
,item_id + ' || ' + CONVERT(VARCHAR(50), PRODUCTION_ID) + ' || ' +
display_description AS ITEM_1
FROM dbo.Equipment INNER JOIN
dbo.ERAT ON SEQUENCE = SEQU INNER JOIN
Track.dbo.item_link ON link_id = PRODUCTION_ID INNER JOIN
Track.dbo.LinkParentDescription ON item_id = item_id
ORDER BY NUM ASC
Basically what I want to do is..
If the NUM value is the same as the next row's NUM value then add a new column populated with
item_id + ' || ' + CONVERT(VARCHAR(50), PRODUCTION_ID) + ' || ' + display_description AS ITEM_2
using the info from the next row.
I've had to anonnymise this code as I was told to do so, so hopefully the code is still valid (lol)
Can you use a window function on SQL Server 2008? The equivalent of LEAD:
MAX(NUM) OVER(ORDER BY NUM ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING)
This expression will give you the NUM value of the next row, where the rows are ordered by NUM ascending. Then just do a comparison with a CASE expression:
CASE
WHEN NUM = MAX(NUM) OVER(ORDER BY NUM ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING)
THEN item_id + ' || ' + CONVERT(VARCHAR(50), PRODUCTION_ID) + ' || '
+ display_description
ELSE YYY
END AS ITEM_2

SQL joins with mulitple where conditions

I have one table that looks like this:
[Jobs]
+-----+-------+---------+
+ ID + Title + Active +
+-----+-------+---------+
+ 1 + Admin + 0 +
+-----+-------+---------+
+ 2 + Mgr + 1 +
+-----+-------+---------+
+ 3 + Emp + 0 +
+-----+-------+---------+
[JobsTxt]
+-------+-------+---------+
+ JobID + Text + Type +
+-------+-------+---------+
+ 1 + test + 1 +
+-------+-------+---------+
+ 1 + test2 + 1 +
+-------+-------+---------+
+ 1 + test3 + 2 +
+-------+-------+---------+
+ 3 + test + 1 +
+-------+-------+---------+
I want to write a query that gives me the Text entries from the JobsTxt table that have Type= 1 and Active=0 in the Jobs table, where JobsTxt.JobID = Jobs.ID
So it'd be something like:
Select [JobsTxt].Text from [JobsText] left join [Jobs] on [JobsTxt].JobId = [Jobs].ID where [JobsTxt].Type = 1 and [Jobs].Active = 0
I'm very new to joins and queries like this, so any help is appreciated!
EXISTS are good if you dont require a JOIN, meaning you only need fields from one of the tables.
SELECT jt.Text
FROM [JobsText] jt
WHERE jt.Type = 1
AND EXISTS
(
SELECT 1
FROM [Jobs] j
WHERE j.ID = jt.JobID
AND j.Active = 0
);
Please excuse, I am not allowed to comment directly on your question. So, let me just put it here, even as I think this may not qualify as an answer.
To me, your SQL statement looks perfectly okay and should deliver what you described. Maybe you could help us out and give some information on the SQL dialect involved (i.e., what database system you are running and what version)?
edit:
it seems you do have a typo:
[...] from [JobsText] [...]
↑ - should there be an 'e'?
Thank you.
Please make use of below query:
DECLARE #Jobs TABLE (ID INT, Title VARCHAR(10), Active BIT )
INSERT INTO #Jobs VALUES
(1,'Admin',0),
(2,'Mgr',1),
(3,'Emp',0)
DECLARE #Jobtxt TABLE ( JobID INT, [Text] VARCHAR(10), [Type] INT)
INSERT INTO #Jobtxt VALUES
(1,'test',1),
(1,'test2',1),
(1,'test3',2),
(3,'test',1)
SELECT
Jt.JobID,Jt.[Text]
FROM
#Jobtxt Jt INNER JOIN #Jobs J ON Jt.JobID = J.ID
WHERE
J.Active = 0 AND Jt.[Type] =1

SQL Group By Query

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;

CAST number as varchar, then update into another table as date

I'll as brief as possible, but start by saying I'm a network guy, not a DBA.
SQL Server Enterprise 11.0.5343
Scenario - Need to get three columns (each with a part of a date) together, and then update another table with the full date.
Source table: UT210AP
Columns:
UTONMM (Utility On Month - 2 digit)
UTONDD (Utility On Day - 2 digit)
UTONYY (Utility On Year - 2 digit)
UTONCV (Utility On Century - 0 = 19xx, 1 = 20xx)
I can select the data into a "date" with this code (the source data is on an IBM AS/400 linked server)
CAST(UTONMM as varchar) + '/' +
CAST(UTONDD as varchar) + '/' +
CASE WHEN UTONCV = '1'
THEN
RIGHT('20' + CONVERT(varchar(4), RIGHT('00' + CONVERT(varchar(4),UTONYY),2)),4)
ELSE
RIGHT('19' + CONVERT(varchar(4), UTONYY),4)
END AS UTON
And I get these results in the column I named "UTON":
4/6/1994
7/1/1988
11/14/1990
6/6/2014
QUESTION:
I have a nightly import job that runs, and I need to get the "date" (like 4/6/1994) into a field called TIME_CONNECT as part of this update statement from the job:
Update [responder].[Temp_RX_CUSTOMERS]
set CustomerID = lf.UTCSID
from [responder].[Temp_RX_CUSTOMERS] LEFT Outer Join
[HTEDTA].[THOR].[HTEDTA].UT210AP lf ON [responder].[Temp_RX_CUSTOMERS].LocationID = lf.UTLCID
where lf.UTOFMM = 0
The "UTOFMM" in the code above is "Utility Off Month", I don't even care about checking for it's value, I just want to get the "UTON" date from the top select statement into the "TIME_CONNECT" field in the "Temp_RX_CUSTOMERS" field.
Is this what you want? This copies the value into the field, assuming time_connect is a string.
Update [responder].[Temp_RX_CUSTOMERS]
set CustomerID = lf.UTCSID,
time_connect = (CAST(UTONMM as varchar) + '/' +
CAST(UTONDD as varchar) + '/' +
(CASE WHEN UTONCV = '1'
THEN RIGHT('20' + CONVERT(varchar(4), RIGHT('00' + CONVERT(varchar(4),UTONYY),2)),4)
ELSE RIGHT('19' + CONVERT(varchar(4), UTONYY),4)
END)
)
from [responder].[Temp_RX_CUSTOMERS] LEFT Outer Join
[HTEDTA].[THOR].[HTEDTA].UT210AP lf
ON [responder].[Temp_RX_CUSTOMERS].LocationID = lf.UTLCID
where lf.UTOFMM = 0;
If time_connect is a date/datetime data type, you can use datefromparts() (available in SQL Server 2012+):
Update [responder].[Temp_RX_CUSTOMERS]
set CustomerID = lf.UTCSID,
time_connect = DATEFROMPARTS(1800 + UTONCV * 100 + UNONYY,
UTONMM, UTONDD)
from [responder].[Temp_RX_CUSTOMERS] LEFT Outer Join
[HTEDTA].[THOR].[HTEDTA].UT210AP lf
ON [responder].[Temp_RX_CUSTOMERS].LocationID = lf.UTLCID
where lf.UTOFMM = 0;

Whilh SQL Structure Is Better?

I have 2 Option For Creating a SQL stucture
For example I need column Code, Name, and Religion :
Option 1 :
+=======+========+=============+
+ Code + Name + Religion_id +
+=======+========+=============+
+ 1 + A + 1 +
+ 2 + B + 2 +
+ 3 + c + 2 +
+=======+========+=============+
+=============+===============+
+ Religion_id + religion_name +
+=============+===============+
+ 1 + Caaaaaa +
+ 2 + Daaaaaa +
+=============+===============+
Option 2 :
+=======+========+
+ Code + Name +
+=======+========+ For Master File
+ 1 + A +
+ 2 + B +
+ 2 + C +
+=======+========+
+=============+===============+
+ Religion_id + religion_name +
+=============+===============+ For Master File
+ 1 + Caaaaaa +
+ 2 + Daaaaaa +
+=============+===============+
+=======+=============+
+ Code + Religion_id +
+=======+=============+ For Transaction File
+ 1 + 1 +
+ 2 + 2 +
+ 3 + 2 +
+=======+=============+
I have done database for around 1 year.
But after I learned at college, I learned that in master file cannot have duplicate data.
In Option 1 there is a duplicate value such as 2 people with same religion. So They create the structure like Option 2.
but IMO Option 2 will take a lot of memory space with a thousand records than Option 1.
My Question is : Which One is the best practice for creating the SQL Structure?
EDit: 1 Name can only has 1 religion
It depends on the relationship between the two tables.
Option 1 is a One-to-many Relationship wherein Religion can contain on many Names. But if the relationship is Many-to-Many, wherein a certain Name can have multiple Religions and that religion can be on many Name, go for Option 2 since it uses association table.