I have a table A like this:
ID Col1
----------------------
1 xyz-abcccc
2 xyz-jkasdasd
3 abcds-asks
4 asdasdasda-as
I want to get output like this:
ID Col1
-------------
1 abcccc
2 jkasdasd
3 asks
4 as
I want get output where anything before the dash - is ignored.
Thanks
charindex() would be a good place to start. The only trick is add a dash within the charindex function as a fail-safe thus avoids throwing an error.
Example
Select ID
,Col1 = substring(Col1,charindex('-',col1+'-')+1,len(Col1))
from YourTable
Returns
ID Col1
1 abcccc
2 jkasdasd
3 asks
4 as
You can use a combination of RIGHT and CHARINDEX functions as well.
Query
select [ID],
case when [Col1] like '%-%' then right([Col1], charindex('-', reverse([Col1]), 1) - 1)
else [Col1] end as [new_col1]
from [your_table_name];
Related
I have a temp table FileTable as follows:
ID FileNameAct FileNameString
1 NULL SalesOrderTarget
2 NULL SalesTarget
3 InventoryMaterialTarget_20220414.xlsx NULL
4 InventoryTarget_20220414.xlsx NULL
5 SalesOrderTarget_20220412.xlsx NULL
6 SalesTarget_20220412.xlsx NULL
Objective: To match the string between FileNameAct and FileNameString and take out the rows that has very close match.
So the resultant table should look like below:
ID FileNameAct FileNameString
1 SalesOrderTarget_20220412.xlsx SalesOrderTarget
2 SalesTarget_20220412.xlsx SalesTarget
I am thinking in below line:
SELECT X.* FROM (SELECT FileNameAct, FileNameString,
CASE WHEN ISNULL(FileNameAct,'') LIKE '%'+ ISNULL(FileNameString,'') + '%' THEN 1 ELSE 0
END AS Flag
FROM #FileTable) X
WHERE X.Flag=1
Clearly, this would not give the correct result.
Can anybody share any thoughts?
You can use a self-join with conditions
Select
b.id,
a.FileNameAct,
b.FileNameString
From #FileTable a
Join #FileTable b
On a.FileNameAct
like concat(b.FileNameString,'%')
Where b.FileNameString is not null;
I'm refactoring very old code. Currently, PHP generates a separate select for every value. Say loc contains 1,2 and data contains a,b, it generates
select val from tablename where loc_id=1 and data_id=a;
select val from tablename where loc_id=1 and data_id=b;
select val from tablename where loc_id=2 and data_id=a;
select val from tablename where loc_id=2 and data_id=b;
...etc which all return either a single value or nothing. That meant I always had n(loc_id)*n(data_id) results, including nulls, which is necessary for subsequent processing. Knowing the order, this was used to generate an HTML table. Both data_id and loc_id can in theory scale up to a couple thousands (which is obviously not great in a table, but that's another concern).
+-----------+-----------+
| data_id 1 | data_id 2 |
+----------+-----------+-----------+
| loc_id 1 | - | 999.99 |
+----------+-----------+-----------+
+ loc_id 2 | 888.88 | - |
+----------+-----------+-----------+
To speed things up, I was looking at replacing this with a single query:
select val from tablename where loc_id in (1,2) and data_id in (a,b) order by loc_id asc, data_id asc;
to get a result like (below) and iterate to build my table.
Rownum VAL
------- --------
1 null
2 999.99
3 777.77
4 null
Unfortunately that approach drops the nulls from the resultset so I end up with
Rownum VAL
------- --------
1 999.99
2 777.77
Note that it is possible that neither data_id or loc_id have any match, in which case I would still need a null, null.
So I don't know which value matches which. I ways to match with the expected loc_id/data_id combination in php if I add loc_id and data_id... but that's getting messy.
Still a novice in SQL in general and that's absolutely the first time I work on PostgreSQL so hopefully that's not too obvious... As I post this I'm looking at two ways to solve this: any in array[] and joins. Will update if anything new is found.
tl;dr question
How do I do a where loc_id in (1,2) and data_id in (a,b) and keep the nulls so that I always get n(loc)*n(data) results?
You can achieve that in a single query with two steps:
Generate a matrix of all desired rows in the output.
LEFT [OUTER] JOIN to actual rows.
You get at least one row for every cell in your table.
If (loc_id, data_id) is unique, you get exactly one row.
SELECT t.val
FROM (VALUES (1), (2)) AS l(loc_id)
CROSS JOIN (VALUES ('a'), ('b')) AS d(data_id) -- generate total grid of rows
LEFT JOIN tablname t USING (loc_id, data_id) -- attach matching rows (if any)
ORDER BY l.loc_id, d.data_id;
Works for any number of columns with any number of values.
For your simple case:
SELECT t.val
FROM (
VALUES
(1, 'a'), (1, 'b')
, (2, 'a'), (2, 'b')
) AS ld (loc_id, data_id) -- total grid of rows
LEFT JOIN tablname t USING (loc_id, data_id) -- attach matching rows (if any)
ORDER BY ld.loc_id, ld.data_id;
where (loc_id in (1,2) or loc_id is null)
and (data_id in (a,b) or data_id is null)
Select the fields you use for filtering, so you know where the values came from:
select loc,data,val from tablename where loc in (1,2) and data in (a,b);
You won't get nulls this way either, but it's not a problem anymore. You know which fields are missing, and you know those are nulls.
I have sql query which returns the following Result :
select * from Emp Order By EmpName asc
Result :
Empid EmpName
1 1
2 2
3 3
A ALL
N NOTALL
but I want output like below :
Empid EmpName
A ALL
N NOTALL
1 1
2 2
3 3
how can I achieve this...
Define a custom sort order either like this:
select *
from Emp
Order By
CASE WHEN IsNumeric(EmpName) = 1 then 0 else 1 end asc,
Empid
or by adding an explict SortOrder column to the table
[Note: ISNUMERIC returns 1 for some characters that are not
numbers, such as plus (+), minus (-), and valid currency symbols such
as the dollar sign ($). For a complete list of currency symbols, see
Using Monetary Data.]
Use a custom sorting logic in your ordering something like:
ORDER BY
CASE
WHEN EMPID = 'A' THEN 1
WHEN EMPID = 'N' THEN 2
ELSE CAST(EMPID AS INT) + 2
END
You could also use the ISNUMERIC function as described in Mitch Wheat's answer to avoid explicitly declaring the cases. However, in case you have a non-alphabetical order e.g. 'G' should appear before 'A', then it would be good to explicitly specify the values.
I need select only strings in my table, but this table has numbers and strings together.
Ex:
ID Name
1 Jacke11
2 Andre
3 Rodrigo11
4 55555
My select need return only Ids: 1, 2, 3.
Thanks
SELECT ID
FROM YourTable
WHERE ISNUMERIC(Name + '.0e0') = 0
As an alternative to Joe's very fine ISNUMERIC solution, you can use PATINDEX to make sure you have an alpha character:
SELECT ID
FROM YourTable
WHERE PATINDEX('%[a-z]%', name) > 0
This may be slightly faster since it will stop searching the string as soon as it gets to the first alpha character.
My question is similar to this one: How to display a table order by code (like 01, 02… then null columns)?, but for SQL Server.
In short, I have a SELECT statement, that returns the following:
ColumnA ColumnB
X NULL
Y 1
Z 2
..where the ordering is done by ColumnB.
How can we force the (columnB = NULL) type of rows to the bottom? ie, the expected result is this:
ColumnA ColumnB
Y 1
Z 2
X NULL
Thank you SOF community.
...or in order to avoid value clashing...
SELECT
ColumnA,
ColumnB
FROM YourTable
ORDER BY
CASE WHEN ColumnB IS NULL THEN 1 ELSE 0 END ASC,
ColumnB
You can also use isnull:
select * from thetable order by isnull(columnb, 99999)
isnull will replace null with the value you provide to it, so in this case, if the column is null, it will replace it with 99999. You can set the value to some big number so it will be at the bottom of the order.
hoping to help someone,
I just wanted to add that I have had a similiar issue, using row_number and partition by -
when it is zero put it at the end sort of thing
and I used the script below (partial view):
,T.MONTHS_TO_AUTOGROWTH
,the_closest_event=ROW_NUMBER() OVER (PARTITION BY SERVERID, DRIVE ORDER BY
CASE WHEN MONTHS_TO_AUTOGROWTH > 0 THEN MONTHS_TO_AUTOGROWTH ELSE 9999
END )
the result is ordered by MONTHS_TO_AUTOGROWTH but zero comes last