I am trying to write a query that matches a tuple of columns from a list. So let's say I have list of first names and last names and I want to match the combination of first and last name of the same index from the database.
first_names = ["Joe", "Freddy", "Michael"]
last_names = ["Jason", "Kruger", "Myers"]
In this case I want query to return some other column for a record that has either name "Joe Jason", "Freddy Kruger" or "Michael Myers".
For me, the obvious way is to group by first and last name and use group concat then match against concatenated field. But I want to try to avoid that. Is there anyway matching by tuples can be done in SQL?
Some databases allow you to express this logic as:
where (firstname, lastname) in ( ('Joe', 'Jason'), ('Freddy', 'Kruger'), ('Michael, 'Myers') )
In all, you can express this using boolean logic:
where (firstname = 'Joe' and lastname = 'Jason') or
(firstname = 'Freddy' and lastname = 'Kruger') or
(firstname = 'Michael' and lastname = 'Myers')
Related
I have a question about SQL. I have created a table in SQL with only one column containing the name of two people (say John and Matt). Later I added a new column into the table with ALTER TABLE. This column will contain the surname of these people.
My question is, in case mmy table contained several people already is there a command to enter the surnames for all the people at once rather than writing one command for each person as in:
INSERT INTO table (Surname) VALUE (John's surname) and
INSERT INTO table (Surname) VALUE (Matt's surname) ?
Thanks in advance
P.D.
I tried something like:
UPDATE foo set Surname=("Parker","Walker") where Name =("John","Matt") but does not work
You want an update. Something like this:
update t
set surname = 'John'' surname'
where firstname = 'John';
You can do this separately for each name. Or use a case expression for multiple ones:
UPDATE foo
SET Surname = (CASE WHEN Name = 'John' THEN 'Parker'
WHEN Name = 'Matt' THEN 'Walker'
END)
WHERE Name IN ('John', 'Matt');
I’m trying to update an email address value from users first- and lastname within the same table.
Pattern for generated Mail: <Firstname>.<Lastname>#test.org
Example Table “Persons”:
Firstname Lastname email
Henley Figueroa none#none.com
Samina Morrison none#none.com
Dev Rowe none#none.com
Wished result for table “Persons”:
Firstname Lastname email
Henley Figueroa Henley.Figueroa#test.org
Samina Morrison Samina.Morrison#test.org
Dev Rowe Dev.Rowe#test.org
SQL Code
UPDATE Persons
SET
email = (SELECT FirstName || "." || LastName ||"#"||"test.org" FROM Persons)
Actual result for table “Persons”:
Firstname Lastname email
Henley Figueroa Henley.Figueroa#test.org
Samina Morrison Henley.Figueroa#test.org
Dev Rowe Henley.Figueroa#test.org
Only the first record of the returned result table is used over and over. Why?
If I ommit the SELECT:
UPDATE Persons
SET
email = FirstName || "." || LastName ||"#"||"test.org"
I get the expected result.
Referring to your answers, I'm extending my question with an example of two tables. One with only names, the second for mail addresses.
Table Persons:
ID*
Firstname
Lastname
1
Henley
Figueroa
2
Samina
Morrison
3
Dev
Rowe
Table Addresses:
ID*
email
1
wrong#wrong.ng
2
wrong#wrong,ng
3
wrong#wro.ng
UPDATE Addresses
SET email = (SELECT Firstname ||"."|| Lastname || "#test.org"
FROM Persons WHERE Persons.id = Addresses.id)
Demo
Here the UPDATE with SET and SELECT works (Every person gets a unique mail address). Shouldn’t I get the same problem here?
From the output of SELECT I see that I get again (as expected) three records.
You have the right syntax for your problem. So the question is why does this not do what you want?
UPDATE Persons
SET email = (SELECT FirstName || "." || LastName ||"#"||"test.org"
FROM Persons
);
In fact, this should produce an error in any SQL engine -- although SQLite can be a bit lax about such errors. Why? The SET is expecting a single value. This code has a subquery that returns three values.
Note: The SQL Fiddle does show that SQLite accepts this syntax. Argggh! You can switch this to Postgres to see the error. With some modifications, to the create code you could also see the same error (subquery returns more than one row) using SQL Server or Oracle or just about any database.
Apparently, SQLite is just arbitrarily choosing one of those values -- the one that it first encounters. And this is the same value for all three rows.
You already know that a subquery is not correct here. You have the correct code in your question.
From Subquery Expressions:
A SELECT statement enclosed in parentheses is a subquery. All types of
SELECT statement, including aggregate and compound SELECT queries
(queries with keywords like UNION or EXCEPT) are allowed as scalar
subqueries. The value of a subquery expression is the first row of
the result from the enclosed SELECT statement. The value of a
subquery expression is NULL if the enclosed SELECT statement returns
no rows.
So the value you get by the subquery is the first row of the rows returned.
Of course, you don't need the SELECT statement.
This is a simple UPDATE statement that involves only the values of the columns of the current row:
UPDATE Persons
SET email = FirstName || '.' || LastName || '#' || 'test.org'
See the demo.
Results:
Firstname
Lastname
email
Henley
Figueroa
Henley.Figueroa#test.org
Samina
Morrison
Samina.Morrison#test.org
Dev
Rowe
Dev.Rowe#test.org
For the 2nd query with the 2 tables:
Shouldn’t I get the same problem here?
No, because the subquery is a correlated subquery, which returns for each row in the table Addresses only 1 row (provided there are no duplicate ids in Persons), the row which matches the condition Persons.id = Addresses.id.
If there is no row that matches the condition then it will return NULL.
I want to update a column with a concatenation of other columns within the same table.
This is for customer names in a table. There are separate columns for "Title" i.e. Mr, Ms, Mrs etc, "FirstName", "MiddleName" and "LastName". I altered the table by adding a new "FullName" column, which I tried to fill with a concatenation of the former columns.
SET [SalesLT].[Customer].[FullName] = (SELECT
Title,
FirstName,
MiddleName,
LastName,
CONCAT(Title,' ',FirstName,' ',MiddleName,' ',LastName) as FullName
FROM [AdventureWorksLT2008R2].[SalesLT].[Customer])
WHERE FullName = NULL;
I'm getting this
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
Since you are updating a column value based on other columns in the same table, you not select them again.
UPDATE [SalesLT].[Customer]
SET [SalesLT].[Customer].[FullName] =
CONCAT(Title,' ',FirstName,' ',MiddleName,' ',LastName)
WHERE FullName is NULL;
Note: I did not change your where clause condition, neither concat function. In some databases you may need to do FullName is NULL instead of FullName = NULL. And in some databases, you may need to concat multiple values with ||.
I have a table called "people" with a column named "name". I would like to select all rows where the name is "bob" or "john". I have tried the following and many variants of it, none of which work. How can I do this correctly?
select * from people where name is bob or john;
Thanks
To compare a column with a value you need to use = not IS
select *
from people
where name = 'bob'
or name = 'john';
Alternatively you can use the IN operator.
select *
from people
where name IN ('bob','john');
Note that string comparison is case-sensitive in SQL. So the above will not return rows where the name is Bob or John
My Products table has almost 10,000 records where i want the "artist" ( varchar ) column name to sort by Firstname and Lastname. In the where clause i am sending initial letter of either first name or lastname. This Query works for few records but not for all, its probably because of the pattern of the records ?
Here is my query
SELECT * FROM Products WHERE SUBSTRING(artist, 1, 1) Like 'C'
Doesnt return the records... the way i want it ...Few of the records of the table ( artist) column are below
Comtesse Mathilde duMonceau de Bergendael
Mulholland, S.J.
Cleminson
NULL
Samuel Jackson
Your LIKE clause is wrong. Also you should not be using LIKE at all here, as you're only filtering by one letter:
.... WHERE LEFT(artist, 1) = 'C'
EDIT LEFT is actually faster than SUBSTRING.
Also, you can not expect anything that's not starting with a C to be returned, as you're explicitly only asking for entries that start with a C.
I guess what you really need is the following:
.... WHERE LEFT(FirstName, 1) = 'C' OR LEFT(LastName, 1) = 'C' ORDER BY LastName, Firstname
If you only have the Artist column, things get complicated, as you actually do need to use LIKE, which makes things pretty slow
.... WHERE Artist LIKE `%C%`
returns any artist, the name of which contains a C anywhere in the name. This would also return these:
Clemens Test
Test Cutler
Arachnophobia
User this where clause
where left(artist, 1) = 'C'
or
where artist like 'C%'