There is a table1
| ID | Attr |
+-----+------------+
| 169 | Jur9 |
| 169 | Jur9_name |
| 169 | Jur10 |
| 169 | Jur10_name |
And query:
select *
from table1
where ID = 169
and ATTR like 'Jur_';
Result:
| ID | Attr |
+-----+------------+
| 169 | Jur9 |
I expect the result:
| ID | Attr |
+-----+------------+
| 169 | Jur9 |
| 169 | Jur10 |
The _ wildcard matches exactly one character. So this expression:
WHERE ATTR like 'Jur_'
Is looking for ATTR values that are four characters that start with 'Jur'.
You can do what you want using LIKE and NOT LIKE:
WHERE ATTR LIKE 'Jur%' AND ATTR NOT LIKE 'JUR%$_%' ESCAPE '$'
That is, followed by anything but not followed by an underscore.
Or, you can use regexp_like():
WHERE REGEXP_LIKE(ATTR, '^JUR[^_]+$')
You can try below -
select *
from table1
where ID = 169
and ATTR not like '%_name'
Related
So... I am currently using Oracle 11.1g and I need to create a query that uses the ID and CusCODE from Table_with_value and checks Table_with_status using the ID to find active CO_status but on different CusCODE.
This is what I have so far - obviously does not work as it should unless CusCODE and ID are provided manually:
SELECT wm_concat(CoID) as active_CO_Status_for_same_ID_but_different_CusCODE
FROM Table_with_status
WHERE
CoID IN (SELECT CoID FROM Table_with_status WHERE ID = Table_with_value.ID AND CusCODE != Table_with_value.CusCODE)) AND Co_status = 'active';
Table_with_value:
|CoID | CusCODE | ID | Value |
|--------|---------|----------|----|
|354223 | 1.432 | 0784296L | 99 |
|321232 | 4.212321.22 | 0432296L | 32 |
|938421 | 3.213 | 0021321L | 93 |
Table_with_status:
|CoID | CusCODE | ID | Co_status|
|--------|--------------|----------|--------|
|354223 | 1.432 | 0784296L | active|
|354232 | 1.432 | 0784296L | inactive |
|666698 | 1.47621 | 0784296L | active |
|666700 | 1.5217 | 0784296L | active |
|938421 | 3.213 | 0021321L | active |
|938422 | 3.213 | 0021321L | active |
|938423 | 3.213 | 0021321L | active |
|321232 | 4.212321.22 | 0432296L | active |
|321232 | 4.212321.22 | 0432296L | active |
|321232 | 1.689 | 0432296L | inactive |
Expected output:
|CoID | active_CO_Status_for_same_ID_but_different_CusCODE | ID | Value |
|--------|---------|----------|----|
|354223 | 666698,666700 | 1.432 | 0784296L | 99 |
|321232 | N/A | 4.212321.22 | 0432296L | 32 |
|938421 | N/A | 3.213 | 0021321L | 93 |
Any idea on how this can be implemented ideally without any PL/SQL for loops, but it should be fine as well since the output dataset is expected < 300 IDs.
I apologize in advance for the cryptic nature in which I structured the question :) Let me know if something is not clear.
From your description and expected output, it looks like you need a left outer join, something like:
SELECT v.CoID,
wm_concat(s.CoID) as other_active_CusCODE -- active_CO_Status_for_same_ID_but_different_CusCODE
v.CusCODE,
v.ID,
v.value
FROM Table_with_value v
LEFT JOIN Table_with_status s
ON s.ID = v.ID
AND s.CusCODE != v.CusCODE
AND s.Co_status = 'active'
GROUP BY v.CoID, v.CusCODE, v.ID, v.value;
SQL Fiddle using listagg() instead of the never-supported and now-removed wm_concat(); with a couple of different approaches if the logic isn't quite what I interpreted. With your sample data they all get:
COID OTHER_ACTIVE_CUSCODE CUSCODE ID VALUE
------ -------------------- ----------- -------- -----
321232 (null) 4.212321.22 0432296L 32
354223 666698,666700 1.432 0784296L 99
938421 (null) 3.213 0021321L 93
Your code looks like it should work, assuming you are referring to the correct tables:
SELECT wm_concat(s.CoID) as active_CO_Status_for_same_ID_but_different_CusCODE
FROM Table_with_status s
WHERE s.CoID IN (SELECT v.CoID
FROM Table_with_value v
WHERE v.ID = s.ID AND
v.CusCODE <> s.CusCODE
) AND
s.Co_status = 'active';
I have two table which has data as below
Table1
+-----+-------+-------------------------+
| ID | value | Test |
+-----+-------+-------------------------+
| 200 | 2456 | yyy xxcv zuio uio tzrue |
| 201 | 2905 | xxx tttt ssrt uio uioe |
| 203 | 34567 | zzz iii ool uiol werts |
| 204 | 2356 | xxx tttt ssrt uio wertz |
| 205 | 3478 | io ser xcv erto klop |
| 206 | 4567 | xxx tttt ssrt uio poiu |
| 207 | 234 | zzz iii ool uiol wert |
+-----+-------+-------------------------+
I would like to create where clause to get rows with like operator.
for ex.
select *
from Table1
where test like '%xxcv zuio%' Or Like '%iii ool%' OR '%xcv erto%' OR '%ssrt uio%' OR '%uio uioe%'
But my problem is that there are more than 15-20 different parameter in where clause, it can also increase latter.
So I have decided to create a new table in database lets called it Table2 with parameter as shown below.
Table2
+----+-----------+
| ID | Parameter |
+----+-----------+
| 20 | xxcv zuio |
| 21 | iii ool |
| 22 | xcv erto |
| 23 | ssrt uio |
| 24 | uio uioe |
+----+-----------+
My question is how can I join this table to give the same result like above query.
I am still learning joins so any advice will be helpful.
You can use exists:
select t1.*
from Table1 t1
where exists (select 1 from table2 t2 where t1.test like concat('%', t2.parameter, '%'))
I don't think using a join is helping in this scenario, and this kind of text searching is not a strong point for SQL Server. Consider building an elasticsearch index or using another system that supports text searching as a primary use case (SQL Server does support full text search if that feature is enabled, but I've always been warned away from it, so don't have experience with it.)
If staying within TSQL is desirable for your particular situation, then I would use the awkward "OR LIKE" syntax. What it lacks in elegance it makes up for in readability.
I have two tables :
Table1
atypcode | ABRNCHCOD | tarikh | codel
1523 | 375 | 1397/06/31 | 375-500-652278-2,375-500-652278-3
2179 | 344 | 1397/06/31 | 344-800-909999-1,344-800-909999-2
2175 | 344 | 1397/06/31 | 344-500-1885840-1,344-500-1885840-2
1523 | 375 | 1397/06/31 | 375-500-2852450-1,375-500-2852450-4
1523 | 375 | 1397/06/31 | 375-500-651108-1,375-500-651108-2,375-500-651108-3
4901 | 154 | 1397/06/31 | 154-305-260752-1,154-200-260752-1,154-800-13557-1
2175 | 344 | 1397/06/31 | 344-500-1075560-1,344-500-1075560-2
3312 | 344 | 1397/06/31 | 344-500-1885840-1,344-500-1885840-2
Table2
tarikh | codel | mande
1397/06/31 | 115-112-1882936-1 | 2798089.00
1397/06/31 | 115-112-1974907-1 | 72580645.00
1397/06/31 | 115-112-1974907-2 | 19052419.00
1397/06/31 | 115-112-2431483-1 | 0.00
1397/06/31 | 115-112-2472323-1 | 2643835.00
1397/06/31 | 115-112-2559539-1 | 1344235.00
1397/06/31 | 115-112-2807485-1 | 113614.00
1397/06/31 | 115-512-2556810-1 | 0.00
1397/06/31 | 115-512-2986840-1 | 130000000.00
1397/06/31 | 115-512-570205-1 | 0.00
and in table1 just one codel is exsist in table2
how i can search table2 in table1 based on codel without "in".
thanks
None of the codes in the second table seem to match to the first table, and also, you should not be storing CSV data like this. That being said, we can try the following trick:
SELECT t2.tarikh, t2.codel, t2.mande
FROM table2 t2
WHERE EXISTS (SELECT 1 FROM table1 t1
WHERE ',' + t1.codel + ',' LIKE '%,' + t2.codel + ',%');
To see how this works, consider the table 1 codel value:
375-500-651108-1,375-500-651108-2,375-500-651108-3
We first surround this value on both sides by comma to give:
,375-500-651108-1,375-500-651108-2,375-500-651108-3,
Then we just have to search a given codel value from table 2, also surrounded by commas, against this string, e.g. search for ,375-500-651108-1,.
https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql?view=sql-server-2017
Try to use the string split function and use it in your join. Please split it in Select clause and use Alias.
STRING_SPLIT ( string , separator )
I have the following table running on Postgres SQL 9.5:
+---+------------+-------------+
|ID | trans_id | message |
+---+------------+-------------+
| 1 | 1234567 | abc123-ef |
| 2 | 1234567 | def234-gh |
| 3 | 1234567 | ghi567-ij |
| 4 | 8902345 | ced123-ef |
| 5 | 8902345 | def234-bz |
| 6 | 8902345 | ghi567-ij |
| 7 | 6789012 | abc123-ab |
| 8 | 6789012 | def234-cd |
| 9 | 6789012 | ghi567-ef |
|10 | 4567890 | abc123-ab |
|11 | 4567890 | gex890-aj |
|12 | 4567890 | ghi567-ef |
+---+------------+-------------+
I am looking for the rows for each trans_id based on a LIKE query, like this:
SELECT * FROM table
WHERE message LIKE '%def-234%'
This, of course, returns just three rows, the three that match my pattern in the message column. What I am looking for, instead, is all the rows matching that trans_id in groups of messages that match. That is, if a single row matches the pattern, get all the rows with the trans_id of that matching row.
That is, the results would be:
+---+------------+-------------+
|ID | trans_id | message |
+---+------------+-------------+
| 1 | 1234567 | abc123-ef |
| 2 | 1234567 | def234-gh |
| 3 | 1234567 | ghi567-ij |
| 4 | 8902345 | ced123-ef |
| 5 | 8902345 | def234-bz |
| 6 | 8902345 | ghi567-ij |
| 7 | 6789012 | abc123-ab |
| 8 | 6789012 | def234-cd |
| 9 | 6789012 | ghi567-ef |
+---+------------+-------------+
Notice rows 10, 11, and 12 were not SELECTed because there was not one of them that matched the %def-234% pattern.
I have tried (and failed) to write a sub-query to get the all the related rows when a single message matches a pattern:
SELECT sub.*
FROM (
SELECT DISTINCT trans_id FROM table WHERE message LIKE '%def-234%'
) sub
WHERE table.trans_id = sub.trans_id
I could easily do this with two queries, but the first query to get a list of matching trans_ids to include in a WHERE trans_id IN (<huge list of trans_ids>) clause would be very large, and would not be a very inefficient way of doing this, and I believe there exists a way to do it with a single query.
Thank you!
This will do the job I think :
WITH sub AS (
SELECT trans_id
FROM table
WHERE message LIKE '%def-234%'
)
SELECT *
FROM table JOIN sub USING (trans_id);
Hope this help.
Try this:
SELECT ID, trans_id, message
FROM (
SELECT ID, trans_id, message,
COUNT(*) FILTER (WHERE message LIKE '%def234%')
OVER (PARTITION BY trans_id) AS pattern_cnt
FROM mytable) AS t
WHERE pattern_cnt >= 1
Using a FILTER clause in the windowed version of COUNT function we can get the number of records matching the predefined pattern within each trans_id slice. The outer query uses this count to filter out irrelevant slices.
Demo here
You can do this.
WITH trans
AS
(SELECT DISTINCT trans_id
FROM t1
WHERE message LIKE '%def234%')
SELECT t1.*
FROM t1,
trans
WHERE t1.trans_id = trans.trans_id;
I think this will perform better. If you have enough data, you can do an explain on both Sub query and CTE and compare the output.
I have two tables (T-SQL):
tblInvalidCharactersList tblMonthsRecords
+-----------+-----------+ +--------+-------------+
| CodePoint | Character | | RecRef | Name |
+-----------+-----------+ +--------+-------------+
| 38 | & | | 21 | Firs> name |
+-----------+-----------+ +--------+-------------+
| 64 | # | | 89 | #Second name|
+-----------+-----------+ +--------+-------------+
| 62 | > | | 321 | Third n«me |
+-----------+-----------+ +--------+-------------+
| 171 | « | | 381 | Fourth name |
+-----------+-----------+ +--------+-------------+
I want to find those records of the tblMonthsRecords which have at least one (or more) character(s) from the Character column of the tblInvalidCharactersList table.
I tried:
SELECT
[RecRef],
[Name]
FROM [tblMonthsRecords]
WHERE [Name] IN (SELECT Character FROM [tblInvalidCharactersList])
and it returns no results at all.
I even tried the NOT IN clause and as you may guess, returns all records.
The reason why I am not hardcoding the characters list within a LIKE clause is because I want the list to be dynamically updated.
You can think the tblInvalidCharactersList as a characters "black list".
I would use exists:
select mr.*
from tblMonthsRecords mr
where exists (select 1
from tblInvalidCharactersList icl
where charindex(icl.Character, mr.name) > 0
);
You don't seem to care about the actual invalid character.
IN will look for exact character match in Name column it will not search for the character in Name column
Use LIKE operator
select Distinct a.*
from tblMonthsRecords a
join tblInvalidCharactersList b
on a.Name like '%' + b.Character + '%'
Another way using charindex
charindex(b.Character,a.Name) > 0