oracle sql ordering results - sql

I have the bellow oracle query:
SELECT
table_to_check.managed_system_serial,
CASE
WHEN infraprod.aix_servers.managed_system_serial IS NULL THEN
'NO'
ELSE
'YES'
END serial_exists,
name
FROM
(
SELECT
column_value managed_system_serial
FROM
TABLE ( sys.odcivarchar2list('BW020', 'D761P', '22DFW', 'BW020') )
) table_to_check
LEFT JOIN infraprod.aix_servers ON table_to_check.managed_system_serial = infraprod.aix_servers.managed_system_serial
The result from running the above is:
I am trying to make the MANAGED_SYSTEM_SERIAL column appear in sequence as the serials are already in the list. What I want to achieve is this:
MANAGED_SYSTEM_SERIAL NAME SERIAL_EXISTS
BW020 NO
D761P gmp3dr YES
22DFW PROM1VIOS2 YES
22DFW PROM1VIOS1 YES
22DFW promdb1 YES
BW020 NO
*The serials above are just a sample. The real number is around 1000 in total.
**There might be multiple entries per serial but this is not a problem, I just need to get them to appear in the results ordered as they are here in this list:
(
'BW020',
'D761P',
'22DFW',
'BW020'
)
As my knowledge in SQL is almost zero this has troubled me for a week and I can't find a solution that fits.
Any help is greatly appreciated.

Include rownum in inner query and use it to sort output:
select t.managed_system_serial, name,
case when a.managed_system_serial is null then 'NO' else 'YES' end SERIAL_EXISTS
from (
select rownum rn, column_value managed_system_serial
from table(sys.odcivarchar2list('BW020', 'D761P', '22DFW', 'BW020'))) t
left join aix_servers a on a.managed_system_serial = t.managed_system_serial
order by t.rn
dbfiddle demo

Are you just looking for order by?
order by MANAGED_SYSTEM_SERIAL

Related

Oracle Query hierarchical level cintaining when case with GROUP BY

I cannot solve a problem with my GROUP BY problem in my query containing CASE...WHEN
Could you help me please with that?
select ID,
CODE,
NOM AS TITLE,
level,
ID_PARENT,
CASE ID_PARENT
WHEN 1111 THEN 'MAIN'
ELSE
(
SUBSTR(
(
SELECT CODE FROM units o
INNER JOIN LIB_UNITS_MV oLab on oLab.ID = o.ID WHERE o.ID = units.ID_PARENT AND LNG_CD = 'ENG'
)
, 7)
)
END AS "PARENT_CODE"
from units
INNER JOIN LIB_UNITS_MV orgLab on orgLab.ID = units.ID
WHERE orgLab.LNG ='ENG'
start with units.id = 1111
connect by prior u.ID = u.ID_PARENT
GROUP BY ID, CODE, NOM, level, ID_PARENT
I obtain the error "not a GROUP BY expression" because I have the WHEN...CASE
Thank you in advance for your help
Regards
Becuase when you group by you need to group by sufficient number of columns, which you use in select statement, outside aggregating functions (min, max, sum etc). So in your case this means - you can either group by all columns used in your case statement, or group by the whole case statement (just copy it over to your group by), or any set of sub-combinations of the whole case, altogether covering it completely. However - since you are not using any aggregate functions I would just do distinct and drop group by altogether.

Change the order by minimum order output in SQL

I am trying to select the minimum of a string however due to sql ordering automatically in lexicographic order, its not in the correct order for what I require.
I currently have 3 seasons where I would like to select the minimum / order by the minimum. The code I currently have is:
Select distinct season from table1 order by season desc;
The order it currently outputs this is:
Spring19
Autumn19
Autumn18
However I need it to order as chronoligical order as the seasons go so:
Autumn18
Spring19
Autumn19
Is there a way that I can change the format to a 'date' without actually changing the format of the text? Or is there another way to do this?
Thanks :)
Most databases support the right() function (if not, they have similar functionality by different names).
So, this should work:
Select distinct season
from table1
order by right(season, 2) asc, season desc;
with seasoncte (season_number, season_year, season) as (
select case when left(season, length(season) -2) = "Spring" then 1
when left(season, length(season) -2) = "Summer" then 2
when left(season, length(season) -2) = "Autumn" then 3
when left(season, length(season) -2) = "Winter then 4
end as season_number,
cast(right(season,2 as int) as season_year,
season
from table1
), seasoncte2 (season_number, season_year, season) as (
select season_number
case when season_year < 39 then 2000 + season_year
case else then 1900 + season_year
end,
season
from seasoncte
)
select t1.season
from table1 t1
join seasoncte2 cte
on t1.season = cte.season
order by cte.season_year, cte.season_number
Code may need tweaking depending on SQL dialect.
Op did not specify that. Or provide rextester link, so code could be tested.

SQL Server: Each GROUP BY expression must contain at least one column that is not an outer reference

scenario 1:
I have two tables INFUSION_APP_APPOINTMENT,INFUSION_APP_NURSE_NOTES where
INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID=INFUSION_APP_APPOINTMENT.ID and i want to find out the INFUSION_APP_NURSE_NOTES.ID's where INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID is same.
for eg. if the INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID = 1 and INFUSION_APP_NURSE_NOTES.ID is 12,15,78, then i want to display all the
INFUSION_APP_NURSE_NOTES.ID's where INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID =1.
i use below script
SELECT INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID,INFUSION_APP_NURSE_NOTES.ID
FROM INFUSION_APP_NURSE_NOTES
GROUP BY INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID,INFUSION_APP_NURSE_NOTES.ID
HAVING COUNT(INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID)>1
but it does not gives me any records.
scenario 2:
I am running below script with the intention to get the duplicate records with different INFUSION_APP_NURSE_NOTES.ID's but same INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID.
SELECT INFUSION_APP_NURSE_NOTES.ID,INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID,INFUSION_APP_NURSE_NOTES.TYPE
FROM INFUSION_APP_NURSE_NOTES
WHERE
EXISTS (
SELECT 1 FROM INFUSION_APP_APPOINTMENT
WHERE
INFUSION_APP_NURSE_NOTES.ENABLE=1
AND INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID=INFUSION_APP_APPOINTMENT.ID
GROUP BY INFUSION_APP_NURSE_NOTES.ID
HAVING COUNT(INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID)>1
)
ORDER BY INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID;
but getting below error
SQL Error(164): Each GROUP BY expression must contain at least one
column that is not an outer reference
how to solve it?
i want the only row which has common APPOINTMENT_ID but different n
The question is unclear. Finding duplicates is typically performed using ranking functions like ROW_NUMBER(). This query :
SELECT *,ROW_NUMBER(PARTITION BY APPOINTMENT_ID ORDER BYID) as RN
FROM INFUSION_APP_NURSE_NOTES
WHERE
ENABLE=1
Will rank notes for the same appointment by ID and return 1, 2, 3 etc starting from the earliest note. ORDER BY ID DESC would return 1 for the latest note.
This can be used in a subquery or CTE to find the first, last or or duplicate records, eg :
with notes as (
SELECT *,ROW_NUMBER(PARTITION BY APPOINTMENT_ID ORDER BYID) as RN
FROM INFUSION_APP_NURSE_NOTES
WHERE
ENABLE=1
)
select *
from notes
where RN=1
Will return the first note per appointment while :
where RN>1
Will return only duplicates.
The question doesn't say what should be done with the duplicates though.
If the question is how to return all notes from appointments with multiple notes, a subquery can be used to return the APPOINTMENT_IDs that have more than one note. There's no need to include the INFUSION_APP_APPOINTMENT table though :
SELECT *
FROM INFUSION_APP_NURSE_NOTES
where
ENABLE=1 AND
APPOINTMENT_ID IN ( SELECT APPOINTMENT_ID
FROM INFUSION_APP_NURSE_NOTES
WHERE
ENABLE=1
group by APPOINTMENT_ID
having count(*)>1)
Try this
SELECT INFUSION_APP_NURSE_NOTES.ID,INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID,INFUSION_APP_NURSE_NOTES.TYPE
FROM INFUSION_APP_NURSE_NOTES
WHERE
EXISTS (
SELECT COUNT(B.APPOINTMENT_ID), B.ID
FROM INFUSION_APP_APPOINTMENT A
INNER JOIN INFUSION_APP_NURSE_NOTES B ON B.APPOINTMENT_ID = A.ID
WHERE
B.ENABLE=1
GROUP BY B.ID
HAVING COUNT(B.APPOINTMENT_ID)>1
)
ORDER BY INFUSION_APP_NURSE_NOTES.APPOINTMENT_ID;

Order by data as per supplied Id in sql

Query:
SELECT *
FROM [MemberBackup].[dbo].[OriginalBackup]
where ration_card_id in
(
1247881,174772,
808454,2326154
)
Right now the data is ordered by the auto id or whatever clause I'm passing in order by.
But I want the data to come in sequential format as per id's I have passed
Expected Output:
All Data for 1247881
All Data for 174772
All Data for 808454
All Data for 2326154
Note:
Number of Id's to be passed will 300 000
One option would be to create a CTE containing the ration_card_id values and the orders which you are imposing, and the join to this table:
WITH cte AS (
SELECT 1247881 AS ration_card_id, 1 AS position
UNION ALL
SELECT 174772, 2
UNION ALL
SELECT 808454, 3
UNION ALL
SELECT 2326154, 4
)
SELECT t1.*
FROM [MemberBackup].[dbo].[OriginalBackup] t1
INNER JOIN cte t2
ON t1.ration_card_id = t2.ration_card_id
ORDER BY t2.position DESC
Edit:
If you have many IDs, then neither the answer above nor the answer given using a CASE expression will suffice. In this case, your best bet would be to load the list of IDs into a table, containing an auto increment ID column. Then, each number would be labelled with a position as its record is being loaded into your database. After this, you can join as I have done above.
If the desired order does not reflect a sequential ordering of some preexisting data, you will have to specify the ordering yourself. One way to do this is with a case statement:
SELECT *
FROM [MemberBackup].[dbo].[OriginalBackup]
where ration_card_id in
(
1247881,174772,
808454,2326154
)
ORDER BY CASE ration_card_id
WHEN 1247881 THEN 0
WHEN 174772 THEN 1
WHEN 808454 THEN 2
WHEN 2326154 THEN 3
END
Stating the obvious but note that this ordering most likely is not represented by any indexes, and will therefore not be indexed.
Insert your ration_card_id's in #temp table with one identity column.
Re-write your sql query as:
SELECT a.*
FROM [MemberBackup].[dbo].[OriginalBackup] a
JOIN #temps b
on a.ration_card_id = b.ration_card_id
order by b.id

How to use Order By clause on a column containing string values separated by comma?

I have a table with a column named Skills which contains comma separated values for different employees like
EmpID Skills
1 C,C++,Oracle
2 Java,JavaScript,PHP
3 C,C++,Oracle
4 JavaScript,C++,ASP
5 C,C++,JavaScript
So I want to write a query which will order all the employees first who knows JavaScript, how can I get this result?
You should not use one attribute to store multiple values. That goes against relation DB principles.
Instead of that you should create additional table to store skills and refer to employee in it. Then, your query will looks like:
SELECT
*
FROM
employees
LEFT JOIN employees_skills
ON employee.id=employees_skills.employee_id
WHERE
employees_skills='JavaScript'
Try this
SELECT *
FROM
(
SELECT *
,CASE WHEN Skills LIKE '%JavaScript%' THEN 0 ELSE 1 END AS Rnk
FROM MyTable
) T
ORDER BY rnk,EmpID
DEMO
OR
SELECT * FROM #MyTable
ORDER BY CASE WHEN Skills LIKE '%JavaScript%' THEN 0 ELSE 1 END,EmpID
select EmpID, Skills
from Table1
order by case when Skills like '%JavaScript%' then 0 else 1 end
Try this:
SELECT *
FROM YourTable
ORDER BY PATINDEX('%JavaScript%', Skills) DESC
But this is a bad way. You should really normalize your table.
For MySQL
select Skills from myTable
order by case Skills
when "Javascript" then 0
when "Java" then 1 when "C++" then 2
end
and so on
For SQL Server
select Skills from myTable
order by case
when Skills="Javascript" then 1
when Skill="Java" then 2
else 3
end
Make sure to start SQL server from 1 (That I'm not sure).
Include an else before end that will show all remaining results.
For more details about SQL Server see this or see this
This works for DB2/400:
with s (id, skill, rest) as
(select id, '', sk from skills
union all
select id, substr(rest, 1, locate(',',rest)-1),
substr(rest,locate(',',rest)+1)
from s
where locate(',',rest) > 0)
select id, skill from s
where skill = 'JavaScript'
order by id