oracle double data sorting - sql

I would like to sort the below kind of data
ms3_fldr01
ms14_fldr01
ms13_fldr01
ms13_fldp01
ms30_fldr01
ms20_fldp01
ms9_fldr01
ms14_fldp01
ms4_fldp01
ms5_fldr01
ms1_fldp01
ms3_fldr01
ms8_fldr01
In such a way that fldp01 will appear first and then fldr01 .
In first appeared data set of fldp01 first (ms) part has to be sorted ( ms1...ms10) also in fldr01 data set first (ms) part has to be sorted . Like below
ms1_fldp01
ms4_fldp01
ms13_fldp01
ms14_fldp01
ms20_fldp01
ms3_fldr01
ms5_fldr01
ms8_fldr01
ms9_fldr01
ms13_fldr01
ms14_fldr01
ms30_fldr01
I have tried in below way but that is not giving data set as per expectation.
select
server, count(*) as C
from TEST
where d_updated_date >= trunc(sysdate-4)
group by server
order by
replace(replace(server,'_fldr01'),'ms') desc,
(case when substr(server,instr(server,'_')+1)='fldp01' then 1
when substr(server,instr(server,'_')+1)='fldp02' then 2
else 0 end) desc;
Can you please help here ??

I think this will do what you want:
order by (case when server like '%_fldp%' then 1 else 2 end),
length(server),
server
(Note: I know that underscore is a special character in like but the above will still work.)
This depends on the fact that the part after the _ is fixed in length. Otherwise, you will need to do a bit more work to separate out the first component.

You can use regexp_substr:
select *
from test
order by regexp_substr(server, '_\w+'),
to_number(regexp_substr(server, '\d+'));

I would expect a solution using ordinary string functions to outperform a regex-based solution.
SELECT *
FROM yourTable
ORDER BY
LENGTH(SUBSTR(server, INSTR(server, '_') + 1)),
SUBSTR(server, INSTR(server, '_') + 1),
LENGTH(SUBSTR(server, 1, INSTR(server, '_') - 1)),
SUBSTR(server, 1, INSTR(server, '_') - 1)

Related

How Do I Modify First Digit of Attribute in XML with SQL?

This is the section of my xml I am trying to modify:
<ORDER ORDER_NAME="10009999"
ORDER_NAME is an attribute.
This is what I have come up with so far and I think it's close, but slightly off.
update table_name set txn_message.modify('replace value of (/ORDER/#ORDER_NAME)[.=1000][1] with "2000"') , txn_status = 1
I want to replace 10009999 with 20009999 (really just something else to make it different so data can be reused, adding a additional character is also fine).
One way is
update t
set txn_message.modify('replace value of (/ORDER/#ORDER_NAME)[1] with concat("2", sql:column("vr"))')
from table_name t
cross apply (
select left(t.txn_message.value('(/ORDER/#ORDER_NAME)[1]','varchar(20)'), 1) vl
, substring (t.txn_message.value('(/ORDER/#ORDER_NAME)[1]','varchar(20)'), 2, 8000) vr
) v
where vl = '1';

Find Substring - SQL

I need to find a substring that is in a text field that is actually partially xml. I tried converting it to xml and then use the .value method but to no avail.
The element(substring) I am looking for is a method name that looks like this:
AssemblyQualifiedName="IPMGlobal.CRM2011.IPM.CustomWorkflowActivities.ProcessChildRecords,
where the method at the end "ProcessChildRecords" could be another name such as "SendEmail". I know I can use the "CustomWorkflowActivities." and the , (comma) to find the substring (method name) but not sure how to accomplish it. In addition, there may be more that one instance listed of the **"CustomWorkflowActvities.<method>"**
Some Clarifications:
Below is my original query. It returns that first occurrence in each row but no additional. For example I might have in the string '...IPM.CustomWorkflowActivities.ProcessChildRecords...' and
'...IPM.CustomWorkflowActivities.GetworkflowContext...'
The current query only returns Approve Time Process,
ipm_mytimesheetbatch,
ProcessChildRecords
SELECT WF.name WFName,
(
SELECT TOP 1 Name
FROM entity E
WHERE WF.primaryentity = E.ObjectTypeCode
) Entity,
Convert(xml, xaml) Xaml,
SUBSTRING(xaml, Charindex('CustomWorkflowActivities.', xaml) + Len('CustomWorkflowActivities.'), Charindex(', IPMGlobal.CRM2011.IPM.CustomWorkflowActivities, Version=1.0.0.0', xaml) - Charindex('CustomWorkflowActivities.', xaml) - Len('CustomWorkflowActivities.'))
FROM FilteredWorkflow WF
WHERE 1 = 1
AND xaml LIKE '%customworkflowactivities%'
AND statecodename = 'Activated'
AND typename = 'Definition'
ORDER BY NAME
If you are using Oracle you could use REGEXP function:
WITH cte(t) as (
SELECT 'AssemblyQualifiedName="IPMGlobal.CRM2011.IPM.CustomWorkflowActivities.ProcessChildRecords,' FROM dual
)
SELECT t,
regexp_replace(t, '.*CustomWorkflowActivities.(.+)\,.*', '\1') AS r
FROM cte;
DBFiddle Demo
SQL Server:
WITH cte(t) as (
SELECT 'AssemblyQualifiedName="IPMGlobal.CRM2011.IPM.CustomWorkflowActivities.ProcessChildRecords,asfdsa'
)
SELECT t,SUBSTRING(t, s, CHARINDEX(',', t, s)-s)
FROM (SELECT t, PATINDEX( '%CustomWorkflowActivities.%', t) + LEN('CustomWorkflowActivities.') AS s
FROM cte
) sub;
DBFiddle Demo 2

How to sort a column in sql based on value B where values in fields are in format A-B-C. I w

I am trying to sort a column in a table where the value in the column is in format 00000197-001-00001 and so on.
I have tried with query
select * from <table name> where <condition> order by column name.
Values are sorted till 00000197-099-001. But after this, the value I am getting is 00000197-1000-001 in my list instead 00000197-100-001.
The result I am getting:
00000197-097-000001
00000197-098-000001
00000197-099-000001
00000197-1000-000001
00000197-100-000001
00000197-1001-000001
00000197-1002-000001
00000197-1003-000001
00000197-1004-000001
00000197-1005-000001
00000197-1006-000001
00000197-1007-000001
00000197-1008-000001
00000197-1009-000001
00000197-1010-000001
00000197-101-000001
00000197-1011-000001
00000197-1012-000001
Expected Result:
00000197-097-000001
00000197-098-000001
00000197-099-000001
00000197-100-000001
00000197-101-000001
.
.
.
00000197-999-000001
00000197-1000-000001
00000197-1001-000001
00000197-1002-000001
00000197-1003-000001
.
.
.
Please suggest the solution.
Many Thanks in advance.
Try this
SELECT *
FROM MyTable1
ORDER BY CAST(SUBSTRING(SUBSTRING(MyCol1, CHARINDEX('-', MyCol1, 0) + 1, 100), 0, CHARINDEX('-', substring(MyCol1, CHARINDEX('-', MyCol1, 0) + 1, 100), 0)) as int)
This works for every string of any length in format X-Y-Z.
Given your sample data, you can do:
order by len(column1), column1
This idea will work in any database, although the length function might be length() rather than len().

LAST REG From a Query SQL

I'm trying to get the last record from this query but i don't know how to do it. I used ROW_NUMBER but my program (Protheus ADVPL) don't have resources to get the last line from a query
SELECT ROW_NUMBER() OVER (ORDER BY B1_MASTER, B1_COD) AS ID,
B1_COD,
B1_DESC,
B1_CATEG,
B1_MASTER,
A2_COMPRAD,
ISNULL((SELECT Sum(C6_QTDVEN * C6_PRCVEN)
FROM SC6010 SC6,
SF4010 SF4,
SC5010 SC5
WHERE C6_FILIAL = '01'
AND C6_PRODUTO = B1_COD
AND SC6.D_E_L_E_T_ <> '*'
AND C5_FILIAL = C6_FILIAL
AND C5_NUM = C6_NUM
AND C5_EMISSAO BETWEEN '20160401' AND '20160404'
AND C5_TIPO = 'N'
AND C5_MODAL = '2'
AND SC5.D_E_L_E_T_ <> '*'
(query have 106 lines so i ll not put everything)
I need the total records in a column, like this:
Tabela
What can i do?
Tks
You can use MAX(field) too.
But, you're using ADVPL, so you could use dbSeek instead to find the last RECNO.
So, using "work area" you can find the last record with this:
TRB->(RECCOUNT())
I changed ROW_NUMBER to ##ROWCOUNT and it works! Tks all

Comparing 2 Columns until the 1st "."

I am new to SQL programming and I am trying to figure out how to get a report to show a mismatch in System Names & DNS Names. Both of the columns are in a table called nodes.
System Name router-1-dc and the DNS would be router-1-dc.domain I am trying to find Nodes that don't match to the "." prior to the domain example for this would be
System Name "router-1-datacenter" and DNS Name "router-1-dc.domain" I would want this example to show on the report page.
The tricky part is that some of the system names have the ".domain" and some don't.
Here is the SQL Query I built however it does not appear to be working as I need it too.
SELECT N. NodeID, N.Caption, N.SysName, N.DNS, N.IP_Address, N.Device_Type
FROM (
SELECT Nodes.NodeID, Nodes.Caption, Nodes.SysName, Nodes.DNS, Nodes.Device_Type, Nodes.IP_Address
FROM Nodes
WHERE CHARINDEX('.',Nodes.SysName)>0 AND CHARINDEX('.',Nodes.DNS)>0
) N
WHERE SUBSTRING(N.SysName, 1, CHARINDEX('.',N.SysName)-1) <> SUBSTRING(N.DNS, 1, CHARINDEX('.',N.DNS)-1)
AND N.Device_Type = 'UPS'
ORDER BY 5 ASC, 2 ASC
Thanks in advance for the help
Try this, or something like it (I've no data to test it against):
SELECT N.NodeID, N.Caption, N.SysName, N.DNS, N.IP_Address, N.Device_Type
from Nodes N
where left(n.sysname, charindex('.', n.sysname + '.') - 1 )
<> left(n.dns, charindex('.', n.dns + '.') - 1)
order by N.IP_Address, N.Caption
The trick is to add a "." to the end of each string for evaluation purposes. If there already is a period in the string, this has no effect, otherwist you get the whole string.