sql join int varchar - sql

I've been searching the questions but havenĀ“t found an answer. I would like to do an inner join with Table 1 and Table 2 , but one field is INT and other is VARCHAR (with the structure "A-INT"). Something like:
Table1 Table2
ID NAME WHATEVER ID USER
1 A-001 --- 1 001
2 A-002 --- 2 002
3 A-003 --- 3 003
3 A-004 --- 4 004
...
How can I construct the query? Something like:
... Table1 INNER JOIN Table2 ON Table1.NAME = Table2.[A-USER] ...

You would need to convert the int value to varchar and concatentate it with 'A-', or get the numeric part of the varchar value and convert to int.
This is done a bit differently depending on what database you are using, for SQL Server it would look like this:
select t1.ID, t1.WHATEVER, t2.USER
from Table1 t1
inner join Table2 t2 on t2.ID = cast(substring(t1.NAME, 3, 3) as int)

Try by concatenation,
SELECT *
FROM Table1 a, Table2 b
WHERE a.Name = 'A-' + b.User
but take note, this decreases the performance.

You want to do inner join on Table1.NAME = Table2.[A-USER].
If Table1.NAME, Table2.[A-USER] column datatype is different means, its not possible to use inner join.

Related

Returning filtered results from sql select

For context this is a search that can be called by and end user, they will provide the comma delimited string containing the Table 3 ID's to be searched and Table 2 text value to search for.
I want to perform a select query that will only return matching results from the CTE where all values in the fieldValuePairTable match. Currently it returns any matches.
DECLARE #fieldvaluepairtable TABLE (Table3Id int, value varchar(max));
INSERT INTO #fieldvaluepairtable SELECT * FROM dbo.split_string_XML('123:york,456:halifax',',');
with cte as (
select Table1.id, Table3.id as t3id, Table2.text
from Table1
inner join Table2 on Table1.id = Table2.Table1Id
inner join Table3 on Table2.id = Table3.Table2Id)
select distinct id
from cte
join #fieldvaluepairtable DataTable on (text like cast( '%' + DataTable.value + '%' as varchar ) and t3id = DataTable.Table3Id)
For example;
A possible result set for the CTE looks like:
id t3id text
---- ----- ---------------
100 123 york
100 456 halifax
200 123 york
200 456 manchester
The select statement would then return
id
----
100
200
I want to select ID's where ALL values in fieldvaluepairtable match rather than when ANY match.
Meaning I want to see the following results
id
----
100
The code will be used in a stored procedure so it needs to be able to handle any number of key value pairs being passed into the fieldvaluepairtable
If I follow you correctly, you can use some relational division technique:
select t1.id
from table1 t1
inner join table2 t2
on t1.id = t2.table1id
inner join table3 t3
on t2.id = t3.table2id
inner join #fieldvaluepairtable x
on t3.text like cast( '%' + x.value + '%' as varchar )
and t3.t3id = x.table3id
group by t1.id
having count(*) = (select count(*) from #fieldvaluepairtable)
Basically this searches for matches, then groups the result by t1.id, and ensures that the number of rows in the group is equal to the count of search criteria.

How to retrieve the data of second table (Table 2) by pointing data of another table (Table 1)

Can someone suggest/help on the below SQL query.
I have two table(Called Table 1 and Table 2), In Table 1 i have the value 11111 in ORG column, using this value i have to identify the correspondence value 1234(Which under MIDA).
MIDA have same value in both table, using this 1234(Which under MIDA, Table 1), i have to retrieve all data from Table 2 where MIDA=1234.
Query should be From Table 1 using ORG value identify the MIDA value and using MIDA value retrieve all data from Table 2 where there are same MIDA(bath Table 1 and Table 2) value.
Table:-1
PK OFFIC MIDA DEPT VER ORG
____________________________________________
123 321 1234 AA1 1.0 11111
Table:-2
FLOW FREE MIDA PRINT TIME ID
____________________________________________________
XYZ A1 1234 test 2019-06-11 1.0
An INNER JOIN answers your question;
SELECT Table2.*
FROM Table2
INNER JOIN Table1
ON Table1.MIDA = Table2.MIDA
WHERE Table1.ORG = '11111'
It sounds like you just need a simple join query:
SELECT t2.*
FROM Table2 t2
INNER JOIN Table1 t2
ON t2.MIDA = t2.MIDA
WHERE
t1.ORG = '11111';
Didn't test:
SELECT * FROM Table2
WHERE MIDA IN (
SELECT MIDA FROM Table1
WHERE ORG = "YOUR ORG VALUE")
EDIT1 Format
You may use JOIN for your requirement. You may find this link for more info JOIN.
For your above query:-
SELECT T2.FLOW, T2.FREE, T2.MIDA, T2.PRINT, T2.TIME, T2.ID
FROM Table2 AS T2
INNER JOIN TABLE1 AS T1 ON T1.MIDA=T2.MIDA
WHERE T1.ORG = 1111 ------ this is optional for fetching only record of org '1111'
SELECT * from TABLE1 t1
INNER JOIN TABLE2 t2
ON t1.MIDA=t2.MIDA
WHERE t1.ORG=1111
given ORG is an int value else it would be '1111'

SQL multiple join from one row with string

i have two table like this:
table1
id(int) | desc(TEXT)
--------------------
0 | "desc1"
1 | "desc2"
table2
id(int) | table1_id(TEXT)
------------------------
0 | "0"
1 | "0;1"
i want to select data into table2 and replace table1_id by the desc field in table1, when i have string with ';' separator it means i have multiple selections.
im able to do it for single selection like this
SELECT table1.desc
FROM table2 LEFT JOIN table1 ON table1.id = CAST(table2.table1_id as integer);
Output wanted with a SELECT on table2 where id = 1:
"desc"
------
"desc1, desc2"
Im using Postgresql10, python3.5 and sqlalchemy
I know how to do it by extracting data and processing it with python then query again but im looking for a way to do it with one SQL query.
PS: I cant modify the table2.
You can convert the CSV value into an array, then join on that:
select string_agg(t1.descr, ',') as descr
from table2 t2
join table1 t1 on t1.id = any (string_to_array(t2.table1_id, ';')::int[])
where t2.id = 1
That is really an abominable data design.
Consequently you will have to write a complicated query to get your desired result:
SELECT string_agg(table1."desc", ', ')
FROM table2
CROSS JOIN LATERAL regexp_split_to_table(table2.table1_id, ';') x(d)
JOIN table1 ON x.d::integer = table1.id
WHERE table2.id = 1;
string_agg
--------------
desc1, desc2
(1 row)

SQL Server - Setting multiple columns from another table

I have two tables.
Table 1
ID Code1 Code2 Code3
10 1.1 1.2 1.3
Table 2
Code Group Category
1.1 a cat1
1.2 b cat1
1.3 c cat2
1.4 d cat3
Now I need to get the outputs in two different forms from these two tables tables
Output 1
ID Group1 Group2 Group3
10 a b c
Output 2
ID cat1 cat2 cat3
10 1 1 0
Here the cat1, cat2, cat3 columns are Boolean in nature since the table 1 did not have any code corresponding to cat3 so the value for this is 0.
I was thinking of doing this with case statements but there are about 1000 codes mapped to about 50 categories. Is their a way to do this? I am struggling to come up with a query for this.
First off, I strongly suggest you look into an alternative. This will get messy very fast, as you're essentially treating rows as columns. It doesn't help much that Table1 is already denormalized - though if it really only has 3 columns, it's not that big of a deal to normalize it again.:
CREATE VIEW v_Table1 AS
SELECT Id, Code1 as Code FROM Table1
UNION SELECT Id, Code2 as Code FROM Table1
UNION SELECT Id, Code3 as Code FROM Table1
If we take you second query, it appears you want all possible combinations of ID and Category, and a boolean of whether that combination appears in Table2 (using Code to get back to ID in Table1).
Since there doesn't appear to be a canonical list of ID and Category, we'll generate it:
CREATE VIEW v_AllCategories AS
SELECT DISTINCT ID, Category FROM v_Table1 CROSS JOIN Table2
Getting the list of represented ID and Category is pretty straightforward:
CREATE VIEW v_ReportedCategories AS
SELECT DISTINCT ID, Category FROM Table2
JOIN v_Table1 ON Table2.Code = v_Table1.Code
Put those together, and we can then get the bool to tell us which exists:
CREATE VIEW v_CategoryReports AS
SELECT
T1.ID, T1.Category, CASE WHEN T2.ID IS NULL THEN 0 ELSE 1 END as Reported
FROM v_AllCategories as T1
LEFT OUTER JOIN v_ReportedCategories as T2 ON
T1.ID = T2.ID
AND T1.Category = T2.Category
That gets you your answer in a normalized form:
ID | Category | Reported
10 | cat1 | 1
10 | cat2 | 1
10 | cat3 | 0
From there, you'd need to do a PIVOT to get your Category values as columns:
SELECT
ID,
cat1,
cat2,
cat3
FROM v_CategoryReports
PIVOT (
MAX([Reported]) FOR Category IN ([cat1], [cat2], [cat3])
) p
Since you mentioned over 50 'Categories', I'll assume they're not really 'cat1' - 'cat50'. In which case, you'll need to code gen the pivot operation.
SqlFiddle with a self-contained example.
These answers assume that all 3 codes are available in table 2. If not, then you should use OUTER joins instead of INNER.
Output 1 can be achieved like this:
select t1.ID,
cd1.Group as Group1,
cd2.Group as Group2,
cd3.Group as Group3
from table1 t1
inner join table2 cd1
on t1.Code1 = cd1.Code
inner join table2 cd2
on t1.Code2 = cd2.Code
inner join table2 cd3
on t1.Code3 = cd3.Code
Output 2 is trickier. Since you want a column for every row in Table2, you could write SQL that writes SQL.
Basically start with this base statement:
select t1.ID,
//THE BELOW WILL BE GENERATED ONCE PER ROW
Case when cd1.Category = '' OR
cd2.Category = '' OR
cd3.Category = '' then convert(bit,1) else 0 end as '',
//END GENERATED CODE
from table1 t1
inner join table2 cd1
on t1.Code1 = cd1.Code
inner join table2 cd2
on t1.Code2 = cd2.Code
inner join table2 cd3
on t1.Code3 = cd3.Code
then you can generate the code in the middle like this:
select distinct 'Case when cd1.Category = '''+t2.Category+''' OR
cd2.Category = '''+t2.Category+''' OR
cd3.Category = '''+t2.Category+''' then convert(bit,1) else 0 end as ['+t2.Category+'],'
from table2 t2
Paste those results into the original SQL statement (strip off the trailing comma) and you should be good to go.
We can use the Pivot feature and build the query dynamically. Some what like below:
Query 1
Select * from
(SELECT Id, Code, GroupCode
FROM Table2 join Table1
ON Table1.Code1 = Table2.Code
OR Table1.Code2 = Table2.Code
OR Table1.Code3 = Table2.Code
) ps
PIVOT
(
Max (GroupCode)
FOR Code IN
( [1.1], [1.2], [1.3])
) AS Result
Query 2
Select * from
(SELECT Id, GroupCode, Category
FROM Table2 join Table1
ON Table1.Code1 = Table2.Code
OR Table1.Code2 = Table2.Code
OR Table1.Code3 = Table2.Code
) ps
PIVOT
(
Count (GroupCode)
FOR Category IN
( [cat1], [cat2], [cat3])
) AS Result
Unfortunately your stuck with a bad design for Table1. A better approach would have been to have 3 rows for ID 10.
But, given your current design, your query will look something like this:
SELECT ID, G1.Group Group1, G2.Group Group2, G3.Group Group3
FROM Table1 T1
INNER JOIN Table2 G1 ON T1.Code1 = G1.Code
INNER JOIN Table2 G2 ON T1.Code2 = G2.Code
INNER JOIN Table2 G3 ON T1.Code3 = G3.Code
and
SELECT ID, G1.Category Cat1, G2.Category Cat2, G3.Category Cat3
FROM Table1 T1
INNER JOIN Table2 G1 ON T1.Code1 = G1.Code
INNER JOIN Table2 G2 ON T1.Code2 = G2.Code
INNER JOIN Table2 G3 ON T1.Code3 = G3.Code
The PIVOT and CROSS APPLY keywords within MSSQL would help you out. Though it's not exactly clear what you are trying to accomplish. CROSS APPLY for performing a join on a correlated subquery and displaying different output for each join, and PIVOT for doing a crosstab on your data.
For table 1 it might be easier if you mash it together into a more normalized style.
WITH cteTab1 (Id, Code) AS
(
SELECT Id, Code1 FROM Table1
UNION ALL
SELECT Id, Code2 FROM Table1
UNION ALL
SELECT Id, Code3 FROM Table1)
SELECT *
FROM Table2 INNER JOIN cteTab1 ON Table2.Code = cteTab1.Code

sql simple 3 table join using same table?

I have two tables:
Table 1
id, name1
Table 2
id, name2a, name2b
Table 2's column names name2a, and name2b are references to table 1's id. I need to create a query that pulls both the names out of table 1 based on the id's used in Table 2.
Therefore, if Table one contained:
1 Peter
2 Paul
And Table 2 contained:
1 1 2
2 2 2
Then a select statement should give me:
Peter Paul
Paul Paul
I've gone around the bend trying to build this SQL and the best I came up with was:
SELECT table1.name AS 'name', table1.name AS 'Other name'
FROM table1, table2
WHERE table1.id = table2.name2a
Which only gives me the name2a column correctly.
Any help appreciated! I guess I need to do a join, but I'm really struggling...
Start with your 2nd table and join TWICE to table 1 (different aliases respectively), then get the name field from each aliased Table1 entry.
select
T2.ID,
TJ1.Name1 as FirstName,
TJ2.Name1 as SecondName
from
Table2 t2
join Table1 TJ1
on t2.Name2a = TJ1.ID
join Table1 TJ2
on t2.Name2b = TJ2.ID
select foo.*, t1.x, t2.y
join t1 on t1.id = foo.a
join t1 as t2 on t2.id = foo.b
If there's a chance that col a or col b is null, use a left join.
Have you tried using an INNER JOIN?
SELECT table1.name AS 'name', table1.name AS 'Other name'
FROM table1 INNER JOIN table2 ON table1.id = table2.name2a;
Sorry if I'm no help, not that great at SQL myself hehe.
Your problem is that you need to reference table1 twice: once for the plain table1.name and again to look up what table2 is pointing at. You can join one table in multiple times if you give them aliases:
SELECT t1.name1, o.name1
FROM table1 t1
JOIN table2 t2 ON t1.id = t2.name2a
JOIN table1 o ON t2.name2b = o.id -- And JOIN back to table1 to get the name1