Query related data based on "like" statement - sql

I have two tables
Table1:
ColumnA (varchar)
Table2:
ColumnB (varchar)
I need to get all rows from T2 where ColumnB is "like" any of the rows from 'ColumnA%'. For example, rows in T1 might be:
Summer09
Fall09
while rows in T2 might be
Spring09 Com101 Sec1
Summer09 Stat400 Sec2
Fall09 CS200 Sec3
In that scenario it would retun the Stat400 and CS200 rows. Is there a way to do this in a single SQL statement?

SELECT T2.*
FROM T1, T2
WHERE T1.ColumnB LIKE T2.ColumnA + '%'
or
SELECT T2.*
FROM T1
INNER JOIN T2 ON T1.ColumnB LIKE T2.ColumnA + '%'
Probably not going to run very fast.

this question points to a bad table design. my good friend Codd always said: do not combine multiple pieces of information into a single column!
t1 coulm should be split, so the semester and/or year should be their own column(s) with a FKs to the t2 table where the class info can be found using an index and no a slow LIKE!!

Related

Is is possible to attach table alias to column names to figure out where columns are coming from?

I have a query that I'm trying to rework that has over 1,000 columns when I select * FROM several tables. I want to know if there is a way in SQL to tag the column alias with the table alias so i can know from which table the columns are from. It looks like the following:
SELECT *
FROM table1 t1
join table2 t2
join table3 t3
join table4 t4
Current column output:
id, id, id, id, name, name, name, name, order, order, order, order
Desired Column output:
t1.id, t1.name, t1.order, t2.id, t2.name, t2.order,t3.id, t3.name, t3.order, t4.id, t4.name, t4.order
this is a very simple example but you can imagine trying to fish out the column you need of a sea of 1,000 columns trying to figure out what table it came from! Any ideas??
I'm not aware of a way to prefix each column with the column alias. However I do know how you could easily break the columns into groups that would allow you to figure out which table each column comes from.
SELECT 'T1' as [Table1]
, t1.*
, 'T2' as [Table2]
, t2.*
, 'T3' as [Table3]
, t3.*
, t4.* as [Table4]
, t4.*
, 'T5' as [Table5]
, t5.*
FROM table1 t1
join table2 t2
join table3 t3
join table4 t4
This would break out the columns into groups by table and it would break a little bookmark before and after each group to help you understand where they're coming.
I know not exactly what you asked for but I believe it would help you a lot in figuring out what's from what tables.
Your other option is as others have said and specifiying the prefix on every column which it sounds like you don't want to do. However it can be a lot quicker to do this if you drag the columns from the Object Explorer - and use ALT-SHIFT to add the prefix to each column.
Here's an article about copying columns from object explorer - https://www.qumio.com/Blog/Lists/Posts/Post.aspx?ID=56
Her's an article about adjusting code using ALT+SHIFT - https://blogs.msdn.microsoft.com/sql_pfe_blog/2017/04/11/quick-tip-shiftalt-for-multiple-line-edits/
The first method would take less than a method, the 2nd method I could see taking less than 10 minutes even for 1,000 columns.
You have to assign non-default column aliases manually:
select t1.id as t1_id, t1.name as t1_name, t1.order as t1_order,
t2.id as t2_id, t2.name as t2_name, t2.order as t2_order,
. . .
You might find that a spreadsheet or query can help, if you have a lot of columns.
Some products may have exceptions, but generally no, you can't do that. You either have to use wildcards (SELECT *) or specify the columns you wish returned by full and complete name.
If you specify columns, you can "alias" them, set the column name to something other than the source name. For example (psuedo-code, leaving out the "ON" clause):
SELECT
T1.Id as T1_Id
,T2.Id as T2_Id
from table1 T1
join table2 T2
Note that you can combine table aliases with wildcards. For example:
SELECT
T2.*
from table1 T1
join table2 T2
join table3 T3
join table4 T5
will return all the columns from table2, and only from table2. This might help in revising your query by getting a list of the available columns in each table.

SQL JOIN table2 ON table2.value in (table1.value)

I want to perform an inner join on a table, based on it's values, like this:
SELECT table2.value FROM table1
INNER JOIN table2 ON table2.key IN (table1.value)
WHERE table1.key = 'test'
Something with the in () is not working, the "in (table1.value)" is not being interpret as "in ('1','2')", it does not show any results.
table1:
KEY VALUE
test '1','2'
table2:
KEY VALUE
1 result1
2 result2
3 result3
I know there is a workaround like this, but I'd like to solve this without an additional SELECT..
SELECT * FROM table2 WHERE table2.value in (SELECT value FROM table1 WHERE key = 'test')
Any ideas?
Thanks,
Lennart
First, your data structure is simply wrong. You should not be storing lists of ids in a string. There are numerous good reasons:
SQL does not have good string processing functions.
You should not store integers as strings.
You should declare proper foreign key relationships.
Your queries cannot take advantage of indexes or partitioning.
The right solution is one row per key and per value.
However, sometimes, we are stuck with other people's really bad design decisions. In that case, you can use like:
SELECT table2.value
FROM table1 t1 INNER JOIN
table2 t2
ON t1.value LIKE '%''' + t2.key + '''%'
WHERE t1.key = 'test';

compare strings of uneven length in TSQL

I have two tables. Both of them contain (dutch) postalcodes.
Those have the format 9999AA and are stored as varchar(6).
In the left table the codes are complete
John Smith 1234AB
Drew BarryMore 3456HR
Ted Bundy 3456TX
Henrov 8995RE
My mother 8995XX
In the right table the codes can be incomplete
1234AB Normal neigbourhood
3456 Bad neighbourhood
8995R Very good neighbourhood
I need to join these tables on the postalcodes. In this example the output would have to be
John Smith Normal neighbourhood
Drew BarryMore Bad neighbourhood
Ted Bundy Bad neighbourhood
Henrov Very good neighbourhood
My mother -unknown-
So I have to join the two tables based on the length of the postal code in the right table.
Any suggestions as to how to do this? I could only come up with a CASE in the ON statement but that was not so smart ;)
If you have no "duplicates" in the second table, you could use like:
SELECT t1.*, t2.col2
FROM table1 AS t1
JOIN table2 AS t2
ON t1.postalcode LIKE t2.postalcode + '%';
However, this is not going to be efficient. Instead, an index on table2(postalcode) and a series of LEFT JOINs is probably faster:
SELECT t1.*, COALESCE(t2a.col2, t2b.col2, t2c.col2)
FROM table1 t1
LEFT JOIN table2 t2a ON t2a.postalcode = t1.postalcode
LEFT JOIN table2 t2b ON t2b.postalcode = LEFT(t1.postalcode, LEN(t1.postalcode) - 1)
LEFT JOIN table2 t2c ON t2c.postalcode = LEFT(t1.postalcode, LEN(t1.postalcode) - 2)
This can take advantage of an index on table2(postalcode). In addition, it only returns one row, even when there are multiple matches in table2, returning the best match.
Use JOIN.
Query
SELECT t1.col1 as name,
coalesce(t2.col2,'-unknown-') as col2
FROM table_1 t1
LEFT JOIN table_2 t2
ON t1.pcode LIKE t2.col1 + '%';
SQL Fiddle
You can Use LEFT(column,4)
select t1.*, t2.col2
from table1 t1 join
table2 t2
on LEFT(t1.postalcode,4)=t2.postalcode
You can use:
on '1234AB' like '1234'+'%'
on firstTable.code like secondTable.code+'%'
In you Join search condition.

DISTINCT COLUMN VALUES FROM ANOTHER TABLE IN JOIN

select t1.key,t2.design,t1.price,t1.gender,t1.store
from table1 t1,table2 t2
where t1.key=t2.key;
This is my query. In this query, column KEY is distinct. I need result with distinct DESIGN values. Help me with this.
from table1 t1 join table2 t2 on t1.key = t2.key
where design like "specific design"
Your request is not precise. There are two things possible:
1) You are talking about duplicate records, i.e. for two records with the same design the columns key, price, gender and store are guaranteed to be equal. Two ways to solve it:
select DISTINCT t1.key,t2.design,t1.price,t1.gender,t1.store
from table1 t1,table2 t2
where t1.key=t2.key;
or
select t1.key,t2.design,t1.price,t1.gender,t1.store
from table1 t1, (select distinct key, design from table2) t2
where t1.key=t2.key;
2) You are talking of duplicate designs and ambigious information related, i.e. for two records for the same design you may get different prices etc. Then you must think about what information you want to get per design. The maximum price? The sum of prices? ...
select t1.key,t2.design,sum(t1.price),max(t1.gender),max(t1.store)
from table1 t1,table2 t2
where t1.key=t2.key
group by t1.key,t2.design;
This gives you records per key and design. If you want records per design only then you would group only by design and decide which key you want to show with it.
A last recommendation: Use explicit join syntax. It is easier to read and less error-prone.
select t1.key, t2.design, t1.price, t1.gender, t1.store
from table1 t1
inner join table2 t2 on t1.key = t2.key;

SQL SELECT across two tables

I am a little confused as to how to approach this SQL query.
I have two tables (equal number of records), and I would like to return a column with which is the division between the two.
In other words, here is my not-working-correctly query:
SELECT( (SELECT v FROM Table1) / (SELECT DotProduct FROM Table2) );
How would I do this? All I want it a column where each row equals the same row in Table1 divided by the same row in Table2. The resulting table should have the same number of rows, but I am getting something with a lot more rows than the original two tables.
I am at a complete loss. Any advice?
It sounds like you have some kind of key between the two tables. You need an Inner Join:
select t1.v / t2.DotProduct
from Table1 as t1
inner join Table2 as t2
on t1.ForeignKey = t2.PrimaryKey
Should work. Just make sure you watch out for division by zero errors.
You didn't specify the full table structure so I will assume a common ID column to link rows in the tables.
SELECT table1.v/table2.DotProduct
FROM Table1 INNER JOIN Table2
ON (Table1.ID=Table2.ID)
You need to do a JOIN on the tables and divide the columns you want.
SELECT (Table1.v / Table2.DotProduct) FROM Table1 JOIN Table2 ON something
You need to substitue something to tell SQL how to match up the rows:
Something like: Table1.id = Table2.id
In case your fileds are both integers you need to do this to avoid integer math:
select t1.v / (t2.DotProduct*1.00)
from Table1 as t1
inner join Table2 as t2
on t1.ForeignKey = t2.PrimaryKey
If you have multiple values in table2 relating to values in table1 you need to specify which to use -here I chose the largest one.
select t1.v / (max(t2.DotProduct)*1.00)
from Table1 as t1
inner join Table2 as t2
on t1.ForeignKey = t2.PrimaryKey
Group By t1.v