Why doesn't this SQL statement work? - sql

SELECT * FROM table1, table2
WHERE table1.user_id = table2.id
AND table1.content = news
AND table1.content_id = 1
that wont work. cant u have two "AND" in a sql statement??
//Tomek

you probably want to quote 'news' as a string...
You also probably want to use an inner join instead (much more efficient)
SELECT * FROM table1
INNER JOIN table2 ON table1.user_id = table2.id
WHERE table1.content = 'news'
AND table1.content_id = 1

news is what? Some sort of parameter? Value of the field? A word which should occur in the field? Most likely your syntax is wrong, see W3Schools WHERE and W3Schools AND/OR operators pages for more information.

let me rewrite that for you with a JOIN statement since it is not 1995 anymore, you also need quotes around news
SELECT * FROM table1 t1
inner join table2 t2 on t1.user_id = t2.id
AND t1.content = 'news'
AND t1.content_id = 1

First let's start with getting rid of that old-style join so that the join and where clauses are clearly separated to make understanding much easier.
SELECT * FROM table1 t1.
JOIN table2 t2
ON t1.user_id = t2.id
WHERE t1.content = news
AND t1.content_id = 1
Now let's discuss what the problem might be. First what error are you receiving as this could be perfectly acceptable syntax? Could the problem be that you have not noted which table news is to come from? If it is in both tables you could be getting an error there. If news is meant to be the value of the column you would want it to be 'news' instead of news. It could also simply be that no records meet your conditions.
Further it is a bad practice to ever use select * and it should never be used in a join as you are returning at least one field twice and that is wasteful of both database and network resources. Always specify only the columns you need. This wastes lots of resources every day when lazy programmers do this in every query.

What do table1 and table2 look like? Can you paste a create script?
I would STRONGLY recommend to use the proper JOIN syntax:
select * from table1
inner join table2 on table1.user_id = table2.id
......
what datatypes is "table1.content" ?
You can most definitely have a lot more than just 2 AND statements in a SQL query - any database that really support any of the SQL-xx standards will support this...

I liked cmartin's response. Also, you can use more than one AND, if needed.

Related

Left Join with Partial match SQL Server

I have 2 tables in SQL Server that I am trying to make a left join from so that all records from table1 are shown and any data from table2 is shown if it exists. They are as follows
Table1
id Customername Jobid
--------------------------------
2754444 Jones 123
2854233 Smith 234
Table2
key Location
-----------------------------
FD#2754444 London
FEC#2854233 Liverpool
I can get an inner join query to work as below - but I obviously get only matching records, (which I dont want - I want all records from table1 and any matching values from table2)
This works:
$query = "select distinct table1.id, table1.customername, table1.jobid, table2.location, table2.[key]
from table1
inner join table2
on table1.id= RIGHT([table2].[key],7)"
So changing it to a left join:
This does not work:
$query = "select distinct table1.id, table1.customername, table1.jobid, table2.location, table2.[key]
from table1
left join table2
on table1.id = RIGHT([table2].[key],7)"
It does not return any of the table2 data. Any advice on what I am doing wrong would be very welcome.
Thanks in advance.
I put together a SQL Fiddle to show that your query should work (based on a guess about datatypes). Given that you've wrapped your queries as strings, that raises the question of whether your problem is actually with SQL, or if the ODBC (or whatever) connection is actually returning a parser error rather than a result set. Have you looked at what the db is providing in return? Have you ensured that there is whitespace between each word, even for line breaks (copying your text as-is shows CRs and LFs, but check your code); otherwise, it's quite possible that you're sending SQL Server something like "SELECT * FROMTABLEWHERETHING" rather than "SELECT * FROM TABLE WHERE".
Thank you all for your input. For some reason the RIGHT was not returning anything so I managed to resolve with :
left JOIN [table2] ON [table1].id= substring([key],(CHARINDEX ('#',[key] , 1)+1),7)
Thanks for all your responses.
Jim

How do I put multiple criteria for a column in a where clause?

I have five results to retrieve from a table and I want to write a store procedure that will return all desired rows.
I can write the query like that temporarily:
Select * from Table where Id = 1 OR Id = 2 or Id = 3
I supposed I need to receive a list of Ids to split, but how do I write the WHERE clause?
So, if you're just trying to learn SQL, this is a short and good example to get to know the IN operator. The following query has the same result as your attempt.
SELECT *
FROM TABLE
WHERE ID IN (SELECT ID FROM TALBE2)
This translates into what is your attempt. And judging by your attempt, this might be the simplest version for you to understand. Although, in the future I would recommend using a JOIN.
A JOIN has the same functionality as the previous code, but will be a better alternative. If you are curious to read more about JOINs, here are a few links from the most important sources
Joins - wikipedia
and also a visual representation of how different types of JOIN work
Another way to do it. The inner join will only include rows from T1 that match up with a row from T2 via the Id field.
select T1.* from T1 inner join T2 on T1.Id = T2.Id
In practice, inner joins are usually preferable to subqueries for performance reasons.

What's the best way to join on the same table twice?

This is a little complicated, but I have 2 tables. Let's say the structure is something like this:
*Table1*
ID
PhoneNumber1
PhoneNumber2
*Table2*
PhoneNumber
SomeOtherField
The tables can be joined based on Table1.PhoneNumber1 -> Table2.PhoneNumber, or Table1.PhoneNumber2 -> Table2.PhoneNumber.
Now, I want to get a resultset that contains PhoneNumber1, SomeOtherField that corresponds to PhoneNumber1, PhoneNumber2, and SomeOtherField that corresponds to PhoneNumber2.
I thought of 2 ways to do this - either by joining on the table twice, or by joining once with an OR in the ON clause.
Method 1:
SELECT t1.PhoneNumber1, t1.PhoneNumber2,
t2.SomeOtherFieldForPhone1, t3.someOtherFieldForPhone2
FROM Table1 t1
INNER JOIN Table2 t2
ON t2.PhoneNumber = t1.PhoneNumber1
INNER JOIN Table2 t3
ON t3.PhoneNumber = t1.PhoneNumber2
This seems to work.
Method 2:
To somehow have a query that looks a bit like this -
SELECT ...
FROM Table1
INNER JOIN Table2
ON Table1.PhoneNumber1 = Table2.PhoneNumber OR
Table1.PhoneNumber2 = Table2.PhoneNumber
I haven't gotten this to work yet and I'm not sure if there's a way to do it.
What's the best way to accomplish this? Neither way seems simple or intuitive... Is there a more straightforward way to do this? How is this requirement generally implemented?
First, I would try and refactor these tables to get away from using phone numbers as natural keys. I am not a fan of natural keys and this is a great example why. Natural keys, especially things like phone numbers, can change and frequently so. Updating your database when that change happens will be a HUGE, error-prone headache. *
Method 1 as you describe it is your best bet though. It looks a bit terse due to the naming scheme and the short aliases but... aliasing is your friend when it comes to joining the same table multiple times or using subqueries etc.
I would just clean things up a bit:
SELECT t.PhoneNumber1, t.PhoneNumber2,
t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2
FROM Table1 t
JOIN Table2 t1 ON t1.PhoneNumber = t.PhoneNumber1
JOIN Table2 t2 ON t2.PhoneNumber = t.PhoneNumber2
What i did:
No need to specify INNER - it's implied by the fact that you don't specify LEFT or RIGHT
Don't n-suffix your primary lookup table
N-Suffix the table aliases that you will use multiple times to make it obvious
*One way DBAs avoid the headaches of updating natural keys is to not specify primary keys and foreign key constraints which further compounds the issues with poor db design. I've actually seen this more often than not.
The first is good unless either Phone1 or (more likely) phone2 can be null. In that case you want to use a Left join instead of an inner join.
It is usually a bad sign when you have a table with two phone number fields. Usually this means your database design is flawed.
You could use UNION to combine two joins:
SELECT Table1.PhoneNumber1 as PhoneNumber, Table2.SomeOtherField as OtherField
FROM Table1
JOIN Table2
ON Table1.PhoneNumber1 = Table2.PhoneNumber
UNION
SELECT Table1.PhoneNumber2 as PhoneNumber, Table2.SomeOtherField as OtherField
FROM Table1
JOIN Table2
ON Table1.PhoneNumber2 = Table2.PhoneNumber
The first method is the proper approach and will do what you need. However, with the inner joins, you will only select rows from Table1 if both phone numbers exist in Table2. You may want to do a LEFT JOIN so that all rows from Table1 are selected. If the phone numbers don't match, then the SomeOtherFields would be null. If you want to make sure you have at least one matching phone number you could then do WHERE t2.PhoneNumber IS NOT NULL OR t3.PhoneNumber IS NOT NULL
The second method could have a problem: what happens if Table2 has both PhoneNumber1 and PhoneNumber2? Which row will be selected? Depending on your data, foreign keys, etc. this may or may not be a problem.
My problem was to display the record even if no or only one phone number exists (full address book). Therefore I used a LEFT JOIN which takes all records from the left, even if no corresponding exists on the right. For me this works in Microsoft Access SQL (they require the parenthesis!)
SELECT t.PhoneNumber1, t.PhoneNumber2, t.PhoneNumber3
t1.SomeOtherFieldForPhone1, t2.someOtherFieldForPhone2, t3.someOtherFieldForPhone3
FROM
(
(
Table1 AS t LEFT JOIN Table2 AS t3 ON t.PhoneNumber3 = t3.PhoneNumber
)
LEFT JOIN Table2 AS t2 ON t.PhoneNumber2 = t2.PhoneNumber
)
LEFT JOIN Table2 AS t1 ON t.PhoneNumber1 = t1.PhoneNumber;
SELECT
T1.ID
T1.PhoneNumber1,
T1.PhoneNumber2
T2A.SomeOtherField AS "SomeOtherField of PhoneNumber1",
T2B.SomeOtherField AS "SomeOtherField of PhoneNumber2"
FROM
Table1 T1
LEFT JOIN Table2 T2A ON T1.PhoneNumber1 = T2A.PhoneNumber
LEFT JOIN Table2 T2B ON T1.PhoneNumber2 = T2B.PhoneNumber
WHERE
T1.ID = 'FOO';
LEFT JOIN or JOIN also return same result. Tested success with PostgreSQL 13.1.1 .

Execute MySQL update query on 750k rows

I've added a field to a MySQL table. I need to populate the new column with the value from another table. Here is the query that I'd like to run:
UPDATE table1 t1
SET t1.user_id =
(
SELECT t2.user_id
FROM table2 t2
WHERE t2.usr_id = t1.usr_id
)
I ran that query locally on 239K rows and it took about 10 minutes. Before I do that on the live environment I wanted to ask if what I am doing looks ok i.e. does 10 minutes sound reasonable. Or should I do it another way, a php loop? a better query?
Use an UPDATE JOIN! This will provide you a native inner join to update from, rather than run the subquery for every bloody row. It tends to be much faster.
update table1 t1
inner join table2 t2 on
t1.usr_id = t2.usr_id
set t1.user_id = t2.user_id
Ensure that you have an index on each of the usr_id columns, too. That will speed things up quite a bit.
If you have some rows that don't match up, and you want to set t1.user_id = null, you will need to do a left join in lieu of an inner join. If the column is null already, and you're just looking to update it to the values in t2, use an inner join, since it's faster.
I should make mention, for posterity, that this is MySQL syntax only. The other RDBMS's have different ways of doing an update join.
There are two rather important pieces of information missing:
What type of tables are they?
What indexes exist on them?
If table2 has an index that contains user_id and usr_id as the first two columns and table1 is indexed on user_id, it shouldn't be that bad.
You don't have an index on t2.usr_id.
Create this index and run your query again, or a multiple-table UPDATE proposed by #Eric (with LEFT JOIN, of course).
Note that MySQL lacks other JOIN methods than NESTED LOOPS, so it's index that matters, not the UPDATE syntax.
However, the multiple table UPDATE is more readable.

have mysql select statement return fully qualified column names like table.field

is there a way to have a mysql select statement return fully qualified column names like "table.field" without using AS for every single field?
like so:
SELECT *
FROM table1
LEFT JOIN table2 on table1.f_ID = table2.ID
and the result would be:
"table1.ID", "table1.name", "table2.ID", "table2.name", ...
If you are using PHP you can use PDO to get this result.
$PDO->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, true);
See SQL Select * from multiple tables for more information.
Not really. You could write some dynamic SQL to accomplish this, but it wouldn't be simple. If you really want the dynamic SQL, let me know and I could try to whip something up.
You can write this as well:
SELECT table1.*, table2.*
FROM table1
LEFT JOIN table2 on table1.f_ID = table2.ID
No need to specify each column, if you want them all
Using fully qualified field names in the statement would yield fully qualified field names in the result set.
SELECT table1.ID, table1.name, table2.ID, table2.name
FROM table1
LEFT JOIN table2 on table1.f_ID = table2.ID
I realize that the burden you wished to get rid of is doing this manually. But if your application has any kind of knowledge about the layout of the database, it can be generated dynamically within the application.
Just my 2 cents
select table1.* , table1='<======'
table2.* , table2='<======'
from table1
left join table2 on table1.f_ID = table2.ID