Searching multiple patterns with single LIKE clause - sql

How could I achieve something like
SELECT *
FROM Table_1
WHERE Column_A CONTAINS ("AB" OR "BE" OR "DE");
I have more than 15 values to put in the contains() so it would be tedious to do it by hand (I mean "where A contains "AB" OR A contains "BE" etc.)
Thanks for any tips,

Try this:
SELECT *
FROM Table_1
WHERE Column_A in ('AB','BE','DE');
This will output all rows in Table_1 where Column_A have any value specified in IN CLAUSE. So it basically works as OR.
Note: This will work if you are searching 'AB' as a whole. If you want all rows having 'AB' or 'BE' anywhere in the column value string then you have to use like clause like this:
SELECT *
FROM Table_1
WHERE Column_A like '%AB%' OR Column_A like '%BE%' OR Column_A like '%DE%';
Update : You could use below one as well, this serves your purpose and you don't have to write LIKE Clause 15-20 times.
Create table employee (name varchar(200))
Insert into employee values('ABC')
Insert into employee values('DEF')
Insert into employee values('BCD')
Insert into employee values('EFG')
Insert into employee values('ADC')
SELECT
distinct name
FROM
(
VALUES
('%A%'),
('%D%')
) AS v (pattern)
CROSS APPLY
( -- your query
SELECT *
FROM employee
WHERE name like v.pattern
) AS x

Related

Adding new column with multiple values per existing record

I'm interested in adding a column to an existing table with a set of explicit values that should duplicate existing records (similar to common join constructs).
For example, say we're starting with a table with a single column:
CREATE TABLE #DEMO (
COLUMN_A NVARCHAR(100) NOT NULL
PRIMARY KEY (COLUMN_A)
);
COLUMN_A
ACCOUNT_001
ACCOUNT_002
ACCOUNT_003
...and I want to add Column_B with row values of 'A', 'B', and 'C'. The end goal would be a table that looks like:
COLUMN_A
COLUMN_B
ACCOUNT_001
A
ACCOUNT_001
B
ACCOUNT_001
C
ACCOUNT_002
A
ACCOUNT_002
B
ACCOUNT_002
C
ACCOUNT_003
A
ACCOUNT_003
B
ACCOUNT_003
C
Is this possible? Bonus Points if there is a name or phrase for this you know of.
So I think you need couple of steps to first insert new rows and then update existing:
alter table #demo add COLUMN_B char(1);
with x as (
select * from (values('A'),('B'))x(B)
)
insert into #demo(COLUMN_A, COLUMN_B)
select COLUMN_A, B
from #DEMO cross join x
update #DEMO set COLUMN_B = 'C'
where COLUMN_B is null
Demo Fiddle

Search from comma separated values

I have user tables which contains column city_id and inside this column city ids are stored as comma separated values as following:
User
user_id user_name city_id
1 ahmar_arshad 1,2,3
2 abdul_muiz 15,2,9
3 abdul_momin 1,2,13
Now I want to search rows which contains city id = 1 from city_id column.
How it can be done?
Here is a general solution, which should work on Postgres:
SELECT *
FROM yourTable
WHERE ',' || city_id || ',' LIKE '%,1,%';
Demo
The trick here is to compare the CSV list of city IDs in the form, e.g. ,1,2,3, against ,ID,, where ID can be any individual city ID.
Note that it would be best to normalize your table and store those city IDs across separate records instead of in CSV strings. This would make querying your data easier, and would probably also increase performance.
If you convert that comma separated list to an array you can use Postgres' powerful array operators:
select *
from cities
where '1' = any (string_to_array(city_id, ','));
If you need to find rows with on of several ID's
select *
from cities
where string_to_array(city_id, ',') && array['1', '2']
The && is the "overlaps" operator for arrays. If you need to find rows that contain all of a list of IDs: you can use the contains operator:
select *
from cities
where string_to_array(city_id, ',') #> array['1', '2']
Check This.
you should use string_to_array to spilt column and then use city_id='1' conditon in where clause.
select * from (
select id,user_name,unnest(string_to_array(city_id, ',')) city_id
from RT
)a where city_id='1'
Check Demo Here.
OutPut
Try this query !
SELECT *
FROM [Table Name]
WHERE city_id LIKE '1,%,%'
OR city_id LIKE '%,1,%'
OR city_id LIKE '%,%,1';
Try this One..
--**********************************************************************************
--Creating Table structure for the reference
create table #test (user_id int,user_name varchar(100),city_id varchar(25))
insert into #test values (1,'ahmar_arshad','1,2,3')
insert into #test values (1,'abdul_muiz','15,2,9')
insert into #test values (1,'abdul_momin','1,2,13')
--select * from #test
--**********************************************************************************
-- Query
select user_id,user_name,city_id from
(
select user_id,user_name,city_id,replace(city_id,',','') as City_ID2
from #test
)A
where City_ID2 like '%1%'
-- Replace comma with star(*) and then search.
--**********************************************************************************
SELECT *
FROM user
WHERE user_id LIKE '%1%';
you can search like keyword on w3school

Create SQL query with given Conditions

I have an SQL query of the form
SELECT
SUM(some_col)
FROM
(some table name here)
WHERE
some_common_condition AND
some_condition1 AND
some_condition2 AND
column_A = 'X'
GROUP BY
column_A;
column_A has some values for which I currently run this query for. Now for each of the unique values of column_A there are some associated conditions.
For eg, if column_A has 3 unique values X,Y,Z, all three have some_common_condition and some specific conditions associated with it,i.e,
for X -> some_condition1 AND some_condition2
for Y -> some_condition3 AND some_condition4
for Z -> some_condition5 AND some_condition6
I want to club all these conditions and make 1 single SQL query,which gives me corresponding SUM(some_col) for all the values of column_A (i.e. X,Y,Z).
Now one obvious way is
SELECT *
FROM(SELECT SUM(some_col) AS val_X FROM (table) WHERE conditions_for_X UNION ALL
SELECT SUM(some_col) AS val_Y FROM (table) WHERE conditions_for_X UNION ALL
SELECT SUM(some_col) AS val_Z FROM (table) WHERE conditions_for_X -- UNION ALL a.s.o.
)
I want to know a solution which only hits the database once. Above query uses 3 select statements, hitting the DB three times, which is bad for scalability reasons.
Does this answer your question?
SELECT SUM(some_col) FROM ...
WHERE
(column_A = 'X' AND some_condition1 AND some_condition2) OR
(column_A = 'Y' AND some_condition3 AND some_condition4) OR
(column_A = 'Z' AND some_condition5 AND some_condition6)
GROUP BY column_A;

Using the distinct function in SQL

I have a SQL query I am running. What I was wanting to know is that is there a way of selecting the rows in a table where the value in on one of those columns is distinct? When I use the distinct function, It returns all of the distinct rows so...
select distinct teacher from class etc.
This works fine, but I am selecting multiple columns, so...
select distinct teacher, student etc.
but I don't want to retrieve the distinct rows, I want the distinct rows where the teacher is distinct. So this query would probably return the same teacher's name multiple times because the student value is different but what I would like is to return rows where the teachers are distinct, even if it means returning the teacher and one student name (because I don't need all the students).
I hope what I am trying to ask is clear but is it possible to use the distinct function on a single column even when selecting multiple columns or is there any other solution to this problem? Thanks.
The above is just an example I am giving. I don't know if using 'distinct' is the solution to my problem. I am not using teacher etc. that was just an example to get the idea accross. I am selecting multiple columns (about 10) from different tables. I have a query to get the tabled result I want. Now I want to query that table to find the unique values in one particular column. So using the teacher example again, say I have wrote a query and I have all the teachers and all the pupils they teach. Now I want to go through each row in this table and email the teacher a message. But I don't want to email the teacher numerous times, just the once, so I want to return all the columns from the table I have, where only the teacher value is distinct.
Col A Col B Col C Col D
a b c d
a c d b
b a a c
b c c c
A query I have produces the above table. Now I want only those rows where Col A values are unique. How would I go about it?
You have misunderstood the DISTINCT keyword. It is not a function and it does not modify a column. You cannot SELECT a, DISTINCT(b), c, DISTINCT(d) FROM SomeTable. DISTINCT is a modifier for the query itself, i.e. you don't select a distinct column, you make a SELECT DISTINCT query.
In other words: DISTINCT tells the server to go through the whole result set and remove all duplicate rows after the query has been performed.
If you need a column to contain every value once, you need to GROUP BY that column. Once you do that, the server now needs to do which student to select with each teacher, if there are multiple, so you need to provide a so-called aggregate function like COUNT(). Example:
SELECT teacher, COUNT(student) AS amountStudents
FROM ...
GROUP BY teacher;
One option is to use a GROUP BY on Col A. Example:
SELECT * FROM table_name
GROUP BY Col A
That should return you:
abcd
baac
Based on the limited details you provided in your question (you should explain how/why your data is in different tables, what DB server you are using, etc) you can approach this from 2 different directions.
Reduce the number of columns in your query to only return the "teacher" and "email" columns but using the existing WHERE criteria. The problem you have with your current attempt is both DISTINCT and GROUP BY don't understand that you one want 1 row for each value of the column that you are trying to be distinct about. From what I understand, MySQL has support for what you are doing using GROUP BY but MSSQL does not support result columns not included in the GROUP BY statement. If you don't need the "student" columns, don't put them in your result set.
Convert your existing query to use column based sub-queries so that you only return a single result for non-grouped data.
Example:
SELECT t1.a
, (SELECT TOP 1 b FROM Table1 t2 WHERE t1.a = t2.a) AS b
, (SELECT TOP 1 c FROM Table1 t2 WHERE t1.a = t2.a) AS c
, (SELECT TOP 1 d FROM Table1 t2 WHERE t1.a = t2.a) AS d
FROM dbo.Table1 t1
WHERE (your criteria here)
GROUP BY t1.a
This query will not be fast if you have a lot of data, but it will return a single row per teacher with a somewhat random value for the remaining columns. You can also add an ORDER BY to each sub-query to further tweak the values returned for the additional columns.
I'm not sure if I am understanding this right but couldn't you do
SELECT * FROM class WHERE teacher IN (SELECT DISTINCT teacher FROM class)
This would return all of the data in each row where the teacher is distinct
distinct requires a unique result-set row. This means that whatever values you select from your table will need to be distinct together as a row from any other row in the result-set.
Using distinct can return the same value more than once from a given field as long as the other corresponding fields in the row are distinct as well.
As soulmerge and Shiraz have mentioned you'll need to use a GROUP BY and subselect. This worked for me.
DECLARE #table TABLE (
[Teacher] [NVarchar](256) NOT NULL ,
[Student] [NVarchar](256) NOT NULL
)
INSERT INTO #table VALUES ('Teacher 1', 'Student 1')
INSERT INTO #table VALUES ('Teacher 1', 'Student 2')
INSERT INTO #table VALUES ('Teacher 2', 'Student 3')
INSERT INTO #table VALUES ('Teacher 2', 'Student 4')
SELECT
T.[Teacher],
(
SELECT TOP 1 T2.[Student]
FROM #table AS T2
WHERE T2.[Teacher] = T.[Teacher]
) AS [Student]
FROM #table AS T
GROUP BY T.[Teacher]
Results
Teacher 1, Student 1
Teacher 2, Student 3
You need to do it with a sub select where you take TOP 1 of student where the teacher is the same.
You may try "GROUP BY teacher" to return what you need.
What is the question your query is trying to answer?
Do you need to know which classes have only one teacher?
select class_name, count(teacher)
from class group by class_name having count(teacher)=1
Or are you looking for teachers with only one student?
select teacher, count(student)
from class group by teacher having count(student)=1
Or is it something else? The question you've posed assumes that using DISTINCT is the correct approach to the query you're trying to construct. It seems likely this is not the case. Could you describe the question you're trying to answer with DISTINCT?
You will need to say how your data is stored in-memory for us to say how you can query it.
But you could do a separate query to just get the distinct teachers.
select distinct teacher from class
I am struggling to understand exactly what you wish to do.. but you can do something like this:
SELECT DISTINCT ColA FROM Table WHERE ...
If you only select a singular column, the distinct will only grab those.
If you could clarify a little more, I could try to help a bit more.
You could use GROUP BY to separate the return values based on a single column value.
All you have to do is select just the columns you want the first one and do a select Distinct
Select Distinct column1 -- where your criteria...
The following might help you get to your solution. The other poster did point to this but his syntax for group by was incorrect.
Get all teachers that teach any classes.
Select teacher_id, count(*)
from teacher_table inner join classes_table
on teacher_table.teacher_id = classes_table.teacher_id
group by teacher_id
Noone seems to understand what you want. I will take another guess.
Select * from tbl
Where ColA in (Select ColA from tbl Group by ColA Having Count(ColA) = 1)
This will return all data from rows where ColA is unique -i.e. there isn't another row with the same ColA value. Of course, that means zero rows from the sample data you provided.
select cola,colb,colc
from yourtable
where cola in
(
select cola from yourtable where your criteria group by cola having count(*) = 1
)
declare #temp as table (colA nchar, colB nchar, colC nchar, colD nchar, rownum int)
insert #temp (colA, colB, colC, colD, rownum)
select Test.ColA, Test.ColB, Test.ColC, Test.ColD, ROW_NUMBER() over (order by ColA) as rownum
from Test
select t1.ColA, ColB, ColC, ColD
from #temp as t1
join (
select ColA, MIN(rownum) [min]
from #temp
group by Cola)
as t2 on t1.Cola = t2.Cola and t1.rownum = t2.[min]
This will return a single row for each value of the colA.
CREATE FUNCTION dbo.DistinctList
(
#List VARCHAR(MAX),
#Delim CHAR
)
RETURNS
VARCHAR(MAX)
AS
BEGIN
DECLARE #ParsedList TABLE
(
Item VARCHAR(MAX)
)
DECLARE #list1 VARCHAR(MAX), #Pos INT, #rList VARCHAR(MAX)
SET #list = LTRIM(RTRIM(#list)) + #Delim
SET #pos = CHARINDEX(#delim, #list, 1)
WHILE #pos > 0
BEGIN
SET #list1 = LTRIM(RTRIM(LEFT(#list, #pos - 1)))
IF #list1 <> ''
INSERT INTO #ParsedList VALUES (CAST(#list1 AS VARCHAR(MAX)))
SET #list = SUBSTRING(#list, #pos+1, LEN(#list))
SET #pos = CHARINDEX(#delim, #list, 1)
END
SELECT #rlist = COALESCE(#rlist+',','') + item
FROM (SELECT DISTINCT Item FROM #ParsedList) t
RETURN #rlist
END
GO

PostgreSQL: Select a single-row x amount of times

A single row in a table has a column with an integer value >= 1 and must be selected however many times the column says. So if the column had '2', I'd like the select query to return the single-row 2 times.
How can this be accomplished?
Don't know why you would want to do such a thing, but...
CREATE TABLE testy (a int,b text);
INSERT INTO testy VALUES (3,'test');
SELECT testy.*,generate_series(1,a) from testy; --returns 3 rows
You could make a table that is just full of numbers, like this:
CREATE TABLE numbers
(
num INT NOT NULL
, CONSTRAINT numbers_pk PRIMARY KEY (num)
);
and populate it with as many numbers as you need, starting from one:
INSERT INTO numbers VALUES(1);
INSERT INTO numbers VALUES(2);
INSERT INTO numbers VALUES(3);
...
Then, if you had the table "mydata" that han to repeat based on the column "repeat_count" you would query it like so:
SELECT mydata.*
FROM mydata
JOIN numbers
ON numbers.num <= mydata.repeat_count
WHERE ...
If course you need to know the maximum repeat count up front, and have your numbers table go that high.
No idea why you would want to do this thought. Care to share?
You can do it with a recursive query, check out the examples in
the postgresql docs.
something like
WITH RECURSIVE t(cnt, id, field2, field3) AS (
SELECT 1, id, field2, field3
FROM foo
UNION ALL
SELECT t.cnt+1, t.id, t.field2, t.field3
FROM t, foo f
WHERE t.id = f.id and t.cnt < f.repeat_cnt
)
SELECT id, field2, field3 FROM t;
The simplest way is making a simple select, like this:
SELECT generate_series(1,{xTimes}), a.field1, a.field2 FROM my_table a;