How to get result from a column with combined data? - sql

data:
id bb
1 14,35
2 5,11,12,125,36
3 3,23,45,15,1
4 651
5 5,1,6
6 1,7
For example, i wan't get id which with value '1'. So id(3,5,6) should return , but not others with '14' or '11'.
DB: Mysql

This is not the most efficient solution but it might give you what you want off the table:
select id from MyTable where bb like '%,1,%' union
select id from MyTable where bb like '1,%' union
select id from MyTable where bb like '%,1' union
select id from MyTable where bb like '1'
cheers

select * from test where find_in_set('1',bbb)
or
select * from test where bbb REGEXP '(^|,)1(,|$)'

Am I missing something?
SELECT *
FROM MyTable
WHERE (id = 3) or (id = 5) or (id = 6)

you can do like this
select * from mytable where id like '14%' or '11%'

Related

SQL - Return a default value when my search returns no results along with search criteria

I am searching with a query
--Code Format
SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3);
If MYTABLE does not contain rows with SWITCH 1,2 or 3 I need default values returned along with the SWITCH value. How do I do it?
Below is my table format
COLA | COLB | COLC | SWITCH
------------------------------
A B C 1
a b c 2
i want a query when I search with
select * from MYTABLE where switch in (1,2,3)
That gets results like this --
COLA | COLB | COLC | SWITCH
------------------------------
A B C 1
a b c 2
NA NA NA 3
--Check to see if any row exists matching your conditions
IF NOT EXISTS (SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3))
BEGIN
--Select your default values
END
ELSE
BEGIN
--Found rows, return them
SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3)
END
if not exists( SELECT 1 from MYTABLE where SWITCH IN (1,2,3))
select default_value
How about:
SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3)
union select 5555, 6666, 7777 where not exists (
SELECT COLA,COLB,COLC from MYTABLE where SWITCH IN (1,2,3)
);
5555, 6666, 7777 being the default row in case there aren't any rows matching your criteria.
Here is one way to tackle this. You need a table of the SWITCH values you want to look at. Then a simple left join makes this super easy.
select ColA
, ColB
, ColC
v.Switch
from
(
values
(1)
, (2)
, (3)
)v (Switch)
left join YourTable yt on yt.Switch = v.Switch
You can Use a Split Function And Left Join As Shown Below:
Select ISNULL(ColA,'NA') As ColA,ISNULL(ColB,'NA') As ColB,ISNULL(ColC,'NA') As ColC,ISNULL(Switch,a.splitdata)
from [dbo].[fnSplitString]('1,2,3',',') a
LEFT JOIN #MYTABLE t on a.splitdata=t.Switch
[dbo].[fnSplitString] is a Split Function with 2 arguments - Delimeter Separated String and Delimeter and Output a Table.
EDIT:
Given the new explanation, I changed the answer completely. I think I got your question now:
SELECT * FROM MYTABLE AS mt
RIGHT JOIN (SELECT 1 AS s UNION SELECT 2 AS s UNION SELECT 3 AS s) AS st
ON st.s = mt.SWITCH
You could change the SELECT 1 AS s UNION SELECT 2 AS s UNION SELECT 3 AS spart to a subquery that results in all possible values SWITCH could assume. E.g.:
SELECT DISTINCT SWITCH FROM another_table_with_all_switches
If all want is the value of switch that is not in MYTABLE, not the whole table with null values, you could try:
SELECT * FROM
(SELECT 1 AS s UNION SELECT 2 AS s UNION SELECT 3) AS st
WHERE st.s NOT IN (SELECT DISTINCT SWITCH FROM MYTABLE)

Merge two SQL queries

How to combine two SQL queries in one?
SELECT *FROM table1 WHERE chapter=88 AND sentence>=23
SELECT *FROM table1 WHERE chapter=89 AND sentence>=1 AND sentence<=23
This is one way
SELECT *FROM table1 WHERE chapter=88 AND sentence>=23
UNION ALL
SELECT *FROM table1 WHERE chapter=89 AND sentence>=1 AND sentence<=23
but you should get into the habit of explicitly listing columns. The columns must align or it won't work.
Here's another way
SELECT * FROM table1
WHERE (chapter=88 AND sentence>=23) OR (chapter=89 AND sentence>=1 AND sentence<=23)
You can join the queries like this:
SELECT * FROM table1
WHERE
(chapter = 88 AND sentence >= 23)
OR
(chapter = 89 AND sentence >= 1 AND sentence <= 23)
SELECT *
FROM TABLE1
WHERE ( CHAPTER = 88
AND SENTENCE >= 23 )
OR ( CHAPTER = 89
AND SENTENCE >= 1
AND SENTENCE <= 23 )
Try this:
SELECT *
FROM TABLE1
WHERE ( CHAPTER = 88
AND SENTENCE >= 23 )
OR ( CHAPTER = 89
AND SENTENCE BETWEEN 1 AND 23 );
You've two ways to do it with a table like this and some sample data
create table table1 (id number, chapter number, sentence number);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (1,65,24);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (2,22,22);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (3,88,25);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (4,89,15);
Insert into TABLE1 (ID,CHAPTER,SENTENCE) values (4,89,33);
You can use a union to munge the two sets together
SELECT *FROM table1 WHERE chapter=88 AND sentence>=23
UNION
SELECT *FROM table1 WHERE chapter=89 AND sentence>=1 AND sentence<=23;
or merge the predicates in the where clause to achieve the same thing
SELECT *FROM table1 WHERE (chapter=88 AND sentence>=23) or
(chapter=89 AND sentence>=1 AND sentence<=23);
both will give this result
| ID| CHAPTER| SENTENCE|
----------------------------------
| 3| 88| 25|
| 4| 89| 15|
Try this:
SELECT * FROM table1
WHERE (chapter=88 and sentence>=23)
OR (chapter=89 and sentence>=1 and sentence<=23)
This should return the results from both queries.
SELECT *
FROM table1
WHERE (chapter = 88 AND sentence >= 23)
OR (chapter = 89 AND sentence >= 1 AND sentence <= 23)
Select *
From table1
where ((chapter=88 AND sentence>=23)
OR (chapter=89 AND sentence>=1 AND sentence<=23));
Also, you can use the BETWEEN keyword in the second clause.
You don't need any Union or Merge statement those operations are redundant. Just change the conditions of your first select.
SELECT *FROM table1 WHERE (chapter=88 OR chapter=89) AND
sentence>= (CASE WHEN chapter = 88
THEN 23
WHEN chapter = 89
THEN 1
END ) AND
sentence <= (CASE WHEN chapter = 89
THEN 23
ELSE sentence
END)
SELECT *FROM table1 WHERE chapter=88 AND sentence>=23
UNION
SELECT *FROM table1 WHERE chapter=89 AND sentence>=1 AND sentence<=23

How to select a number thats in a string format

I Have a table that has a column that can have values like
Id FileNumber
------------------
1 0025
2 CDE01
3 0035
4 25
5 45
6 250
7 XYZ1
8 2500
Now if I want to select the row that has the FileNumber 25, how can I get that. I do not want the row that has 250 or 2500. The search should only get 0025 and 25. This column is of type varchar. However, I should be able to search by any value like XYZ1 OR 0025 OR 250
I tried using the Like operator eg: WHERE FileNumber Like '%25%' also tried WHERE FileNumber Like '25%' does not give me the desired results
Any help will be greatly appreciated
Based on the sample data, I'll assume the numbers you need to retrieve are integers. So you could cast them to integers if they are numeric using something like this:
CASE WHEN ISNUMERIC(s.col) = 1 THEN CAST(s.col AS INT) END
Example:
WITH sample AS (
SELECT '0025' AS col
UNION ALL
SELECT 'CDE01'
UNION ALL
SELECT '0035'
UNION ALL
SELECT '25'
UNION ALL
SELECT '45'
UNION ALL
SELECT '250'
UNION ALL
SELECT 'XYZ1'
UNION ALL
SELECT '2500')
SELECT CASE WHEN ISNUMERIC(s.col) = 1 THEN CAST(s.col AS INT) END
FROM sample s
You can use that in a derived table/inline view to compare against. It's possible you could add a computed column using the logic to the table.
You want anything that
matches exactly (25)
ends in with only leading zeroes) (0025)
This code does that with some LIKE matching
WITH sample AS (
SELECT '0025' AS col
UNION ALL SELECT 'CDE01'
UNION ALL SELECT '0035'
UNION ALL SELECT '25'
UNION ALL SELECT '45'
UNION ALL SELECT '250'
UNION ALL SELECT 'XYZ1'
UNION ALL SELECT 'XYZ125'
UNION ALL SELECT '125'
UNION ALL SELECT '2500')
SELECT
s.col
FROM
sample s
WHERE
col = '25'
OR
(REPLACE(col, '25', '00') NOT LIKE '%[^0]%' AND col LIKE '%25')
How about this?
SELECT * FROM [TABLE NAME]
WHERE FILENUMBER LIKE '%25'
Please use this to get all the rows from the table having the values that exactly matches the comma seprated values.
SELECT * FROM TABNAME WHERE FILENUMBER in ('25','0025','xyz')
It will select all the rows who contains the filenumber as 25 or 0025 or xyz.
If it's safe to fix the data...do that.
Try something like this
update
set filename = cast(filename as int)
where filename like '%[1-9]%' --has a number in it
and filename like '%[^a-z]%' -- doesn't have a letter in it

SELECT DISTINCT for data groups

I have following table:
ID Data
1 A
2 A
2 B
3 A
3 B
4 C
5 D
6 A
6 B
etc. In other words, I have groups of data per ID. You will notice that the data group (A, B) occurs multiple times. I want a query that can identify the distinct data groups and number them, such as:
DataID Data
101 A
102 A
102 B
103 C
104 D
So DataID 102 would resemble data (A,B), DataID 103 would resemble data (C), etc. In order to be able to rewrite my original table in this form:
ID DataID
1 101
2 102
3 102
4 103
5 104
6 102
How can I do that?
PS. Code to generate the first table:
CREATE TABLE #t1 (id INT, data VARCHAR(10))
INSERT INTO #t1
SELECT 1, 'A'
UNION ALL SELECT 2, 'A'
UNION ALL SELECT 2, 'B'
UNION ALL SELECT 3, 'A'
UNION ALL SELECT 3, 'B'
UNION ALL SELECT 4, 'C'
UNION ALL SELECT 5, 'D'
UNION ALL SELECT 6, 'A'
UNION ALL SELECT 6, 'B'
In my opinion You have to create a custom aggregate that concatenates data (in case of strings CLR approach is recommended for perf reasons).
Then I would group by ID and select distinct from the grouping, adding a row_number()function or add a dense_rank() your choice. Anyway it should look like this
with groupings as (
select concat(data) groups
from Table1
group by ID
)
select groups, rownumber() over () from groupings
The following query using CASE will give you the result shown below.
From there on, getting the distinct datagroups and proceeding further should not really be a problem.
SELECT
id,
MAX(CASE data WHEN 'A' THEN data ELSE '' END) +
MAX(CASE data WHEN 'B' THEN data ELSE '' END) +
MAX(CASE data WHEN 'C' THEN data ELSE '' END) +
MAX(CASE data WHEN 'D' THEN data ELSE '' END) AS DataGroups
FROM t1
GROUP BY id
ID DataGroups
1 A
2 AB
3 AB
4 C
5 D
6 AB
However, this kind of logic will only work in case you the "Data" values are both fixed and known before hand.
In your case, you do say that is the case. However, considering that you also say that they are 1000 of them, this will be frankly, a ridiculous looking query for sure :-)
LuckyLuke's suggestion above would, frankly, be the more generic way and probably saner way to go about implementing the solution though in your case.
From your sample data (having added the missing 2,'A' tuple, the following gives the renumbered (and uniqueified) data:
with NonDups as (
select t1.id
from #t1 t1 left join #t1 t2
on t1.id > t2.id and t1.data = t2.data
group by t1.id
having COUNT(t1.data) > COUNT(t2.data)
), DataAddedBack as (
select ID,data
from #t1 where id in (select id from NonDups)
), Renumbered as (
select DENSE_RANK() OVER (ORDER BY id) as ID,Data from DataAddedBack
)
select * from Renumbered
Giving:
1 A
2 A
2 B
3 C
4 D
I think then, it's a matter of relational division to match up rows from this output with the rows in the original table.
Just to share my own dirty solution that I'm using for the moment:
SELECT DISTINCT t1.id, D.data
FROM #t1 t1
CROSS APPLY (
SELECT CAST(Data AS VARCHAR) + ','
FROM #t1 t2
WHERE t2.id = t1.id
ORDER BY Data ASC
FOR XML PATH('') )
D ( Data )
And then going analog to LuckyLuke's solution.

sql select to start with a particular record

Is there any way to write a select record starting with a particular record? Suppose I have an table with following data:
SNO ID ISSUE
----------------------
1 A1 unknown
2 A2 some_issue
3 A1 unknown2
4 B1 some_issue2
5 B3 ISSUE4
6 B1 ISSUE4
Can I write a select to start showing records starting with B1 and then the remaining records? The output should be something like this:
4 B1 some_issue2
6 B1 ISSUE4
1 A1 unknown
2 A2 some_issue
3 A1 unknown2
5 B3 ISSUE4
It doesn't matter if B3 is last, just that B1 should be displayed first.
Couple of different options depending on what you 'know' ahead of time (i.e. the id of the record you want to be first, the sno, etc.):
Union approach:
select 1 as sortOrder, SNO, ID, ISSUE
from tableName
where ID = 'B1'
union all
select 2 as sortOrder, SNO, ID, ISSUE
from tableName
where ID <> 'B1'
order by sortOrder;
Case statement in order by:
select SNO, ID, ISSUE
from tableName
order by case when ID = 'B1' then 1 else 2 end;
You could also consider using temp tables, cte's, etc., but those approaches would likely be less performant...try a couple different approaches in your environment to see which works best.
Assuming you are using MySQL, you could either use IF() in an ORDER BY clause...
SELECT SNO, ID, ISSUE FROM table ORDER BY IF( ID = 'B1', 0, 1 );
... or you could define a function that imposes your sort order...
DELIMITER $$
CREATE FUNCTION my_sort_order( ID VARCHAR(2), EXPECTED VARCHAR(2) )
RETURNS INT
BEGIN
RETURN IF( ID = EXPECTED, 0, 1 );
END$$
DELIMITER ;
SELECT SNO, ID, ISSUE FROM table ORDER BY my_sort_sort( ID, 'B1' );
select * from table1
where id = 'B1'
union all
select * from table1
where id <> 'B1'