mysql select data from multiple rows - sql

I have a table
id, name, keyword
1 bob guy
2 bob developer
3 mary girl
4 joe guy
Q1 : What would be the sql to get back the row (bob) containing both keywords 'guy' AND 'developer'?
Intuitively, I thought it'd be SELECT * FROM TABLE WHERE keyword = 'guy' AND keyword = 'developer'
Q2: But I suppose the first conditional AND removes the 2nd row (bob, developer) which causes the sql to return no result? Am I correct about this speculation?

SELECT * FROM TABLE WHERE keyword = 'guy' AND name in (SELECT name FROM TABLE WHERE keyword = 'developer')

Related

SQL: Need help listing all the unique names and the number of times they appear in two columns

I've got 2 columns filled with names. The list is seemingly random and a person's name could show up in column A or column B (but never in both at the same instance). I want to write a query that will tell me all the names and the number of times each person is in either list. Here's an example of what I'm talking about
Col A
Col B
Mark
Cheryl
Andy
Tom
James
Mark
Tom
Ann
Cheryl
Jeff
Andy
Mark
I'm looking for a query/function that will give me the list of names and the number of times they were seen in either column.
Any help is always appreciated!
Assuming your table name is names and your columns are a,b then this should work:
select n.name, count(n.name)
from (
select a as name from names
union all
select b as name from names
) n
group by n.name;
SELECT
Name,
COUNT(1) as cnt
FROM (
SELECT ColA As Name FROM my_table UNION ALL
SELECT ColB As Name FROM my_table
) t
GROUP BY
Name
db fiddle

Node / Postgres SQL Select distinct entries then put all other entries with the same reference into one column

this question was probably asked somewhere but I can't seem to phrase it correctly in the search to find an accurate answer.
I'm doing a query on a Postgres DB, it has quite a few joins, the results are something like this:
WON | name | item
1 Joe A
1 Joe B
2 Smith A
So one row for each entry, I need to somehow get the result back as such:
WON | name | item
1 Joe A, B
2 Smith A
This can be done in the query or with NodeJS, there are hundreds to thousands of results for the query, so getting a distinct row (WON 1) then searching the DB for all entries that match it then repeating for the rest isn't feasible, so this may be better done in Node / Javascript, but I'm somewhat new to that, what would be a (somewhat) efficient way to do this?
If there IS a way to do this in the query itself then that would be my preference though.
Thanks
A sql approach:
SELECT won, name
,STRING_AGG(item, ',' ORDER BY item) AS items
FROM myTable
GROUP BY won, name
ORDER BY won, name
You can use GROUP BY and string_agg to cancat rows, somelike this:
Create table:
CREATE TABLE test
(
won int,
name character varying(255),
item character varying(255)
);
insert into test (won, name, item) values (1,'Joe', 'A'),(1, 'Joe', 'B'),(2, 'Smith', 'A')
And do this in the query:
select won, name, string_agg(item, ',') from test group by won, name order by won
See this example in sqlFiddle

Can IBM DB2 return a 0 (zero) when no records are found?

for example :
I have a table with student ID and student grades
-----------------------
ID | grades
-----------------------
1 | 80
2 | 28
-----------------------
I want to get 0 when I query about ID = 3
can I do that ?
like select grades from student where id = 3 .
I want to get 0 because ID is not in the table
Run a select command with the reserved function called count:
select count(*) from STUDENT.GRADES where ID=3
It should be just like that.
Maybe this will do what you want:
SELECT ID, MAX(Grades)
FROM (SELECT ID, Grade FROM Students WHERE ID = 3
UNION
VALUES (3, 0) -- Not certain of syntax here
)
GROUP BY ID
The basic idea is that students present in the table will have two rows and the MAX will pick their proper grade (assuming that there are no circumstances where the grade is coded as a negative value). Students that are not represented will have just the one row with a grade of 0. The repeated 3 is the ID of the student being sought.
Have fun chasing down the full syntax. I started at Queries in the DB2 9.7 Information Centre, but ran out of patience before I got a good answer — and I don't have DB2 to experiment on. You might need to write SELECT ID, Grades FROM VALUES (3, 0), or there might be some other magical incantation that does the job. You could probably use SELECT 3 AS ID, 0 AS Grades FROM SYSIBM.SYSTABLES WHERE TABID = 1, but that's a clumsy expression.
I've kept with the column name Grades (plural) even though it looks like it contains one grade. It is depressing how often people ask questions about anonymous tables.

SQL to normalize existing (many-to-many) data

Summary:
See below for Details. I'm copying the [unanswered] many-to-many question here to the top for readability:
Given the "Input" table, what is the SQL to generate the 3rd "Output"
table (Person_plays_Instrument)?
Current input (1 table):
OriginalTable:
PersonId PersonName Instrument_1 Instrument_2 Instrument_3 MailingAddress HomePhone
--------|----------|------------|------------|------------|--------------|------------
1 Bob Violin Viola Trumpet someplace 111-111-1111
2 Suzie Cello Flute <null> otherplace 222-222-2222
3 Jim Violin <null> <null> thirdplace 333-333-3333
Desired output (3 tables):
Person:
Id Name MailingAddress HomePhone
--|------|--------------|------------
1 Bob someplace 111-111-1111
2 Suzie otherplace 222-222-2222
3 Jim thirdplace 333-333-3333
Instrument:
Id Name
--|-------
1 Violin
2 Cello
3 Viola
4 Flute
5 Trumpet
Person_plays_Instrument:
PersonId InstrumentId
--------|------------
1 1
1 3
1 5
2 2
2 4
3 1
Details:
I have a single flat SQL table which started out as a spreadsheet. I'd like to normalize it. I'll split this into 1 question for each table.
Questions 1 and 2 have been answered, but I am leaving them in in case others find them helpful.
Questions:
Question #1: [answered]
How do I generate Person table?
Answer #1:
This wonderful post gets me 2/3rds of the way there. For the one-to-many tables, I'm set. Here's the code:
[add autonumber field to OriginalTable, name it PersonId]
[create empty Person table with Id, Name, MailingAddress, HomePhone fields]
INSERT INTO Person (Id, Name, MailingAddress, HomePhone)
SELECT o.PersonID, o.PersonName, o.MailingAddress, o.HomePhone
FROM OriginalTable as o
WHERE o.PersonName Is Not Null;
Question #2: [attempted] (better version by #Branko in Accepted Answer)
How do I generate Instrument table?
Answer #2:
Again, one-to-many. At first, the multiple columns had me stumped.
The solution came in two parts:
I'd just have to repeat the INSERT command, once for each column.
Using this post and the IN operator, I can check each time to confirm I hadn't already inserted that value.
Here's the code:
[create empty Instrument table with Id[autonumber], Name fields]
INSERT INTO Instrument (Name)
SELECT Distinct o.Instrument_1
FROM OriginalTable as o
WHERE o.Instrument_1 Is Not Null
AND o.Instrument_1 Not In (SELECT Name from Instrument);
INSERT INTO Instrument (Name)
SELECT Distinct o.Instrument_2
FROM OriginalTable as o
WHERE o.Instrument_2 Is Not Null
AND o.Instrument_2 Not In (SELECT Name from Instrument);
INSERT INTO Instrument (Name)
SELECT Distinct o.Instrument_3
FROM OriginalTable as o
WHERE o.Instrument_3 Is Not Null
AND o.Instrument_3 Not In (SELECT Name from Instrument);
Question #3: [unanswered]
How do I generate Person_plays_Instrument table?
Assuming there is OriginalTable.PersonID, which you haven't shown us, but is implied by your own answer #1, the answer #3 can be expressed simply as:
INSERT INTO Person_plays_Instrument (PersonId, InstrumentId)
SELECT PersonID, Instrument.Id
FROM
OriginalTable
JOIN Instrument
ON OriginalTable.Instrument_1 = Instrument.Name
OR OriginalTable.Instrument_2 = Instrument.Name
OR OriginalTable.Instrument_3 = Instrument.Name;
BTW, there is a more concise way to express the answer #2:
INSERT INTO Instrument (Name)
SELECT *
FROM (
SELECT o.Instrument_1 I
FROM OriginalTable as o
UNION
SELECT o.Instrument_2
FROM OriginalTable as o
UNION
SELECT o.Instrument_3
FROM OriginalTable as o
) Q
WHERE I IS NOT NULL;
And here is a fully working SQL Fiddle example for MS SQL Server. Other DBMSes should behave similarly. BTW, you should tag your question appropriately to indicate your DBMS.

SQL select replace integer with string

Goal is to replace a integer value that is returned in a SQL query with the char value that the number represents. For example:
A table attribute labeled ‘Sport’ is defined as a integer value between 1-4. 1 = Basketball, 2 = Hockey, etc. Below is the database table and then the desired output.
Database Table:
Player Team Sport
--------------------------
Bob Blue 1
Roy Red 3
Sarah Pink 4
Desired Outputs:
Player Team Sport
------------------------------
Bob Blue Basketball
Roy Red Soccer
Sarah Pink Kickball
What is best practice to translate these integer values for String values? Use SQL to translate the values prior to passing to program? Use scripting language to change the value within the program? Change database design?
The database should hold the values and you should perform a join to another table which has that data in it.
So you should have a table which has say a list of people
ID Name FavSport
1 Alex 4
2 Gnats 2
And then another table which has a list of the sports
ID Sport
1 Basketball
2 Football
3 Soccer
4 Kickball
Then you would do a join between these tables
select people.name, sports.sport
from people, sports
where people.favsport = sports.ID
which would give you back
Name Sport
Alex Kickball
Gnat Football
You could also use a case statement eg. just using the people table from above you could write something like
select name,
case
when favsport = 1 then 'Basketball'
when favsport = 2 then 'Football'
when favsport = 3 then 'Soccer'
else 'Kickball'
end as "Sport"
from people
But that is certainly not best practice.
MySQL has a CASE statement. The following works in SQL Server:
SELECT
CASE MyColumnName
WHEN 1 THEN 'First'
WHEN 2 THEN 'Second'
WHEN 3 THEN 'Third'
ELSE 'Other'
END
In oracle you can use the DECODE function which would provide a solution where the design of the database is beyond your control.
Directly from the oracle documentation:
Example: This example decodes the value warehouse_id. If warehouse_id is 1, then the function returns 'Southlake'; if warehouse_id is 2, then it returns 'San Francisco'; and so forth. If warehouse_id is not 1, 2, 3, or 4, then the function returns 'Non domestic'.
SELECT product_id,
DECODE (warehouse_id, 1, 'Southlake',
2, 'San Francisco',
3, 'New Jersey',
4, 'Seattle',
'Non domestic') "Location"
FROM inventories
WHERE product_id < 1775
ORDER BY product_id, "Location";
The CASE expression could help. However, it may be even faster to have a small table with an int primary key and a name string such as
1 baseball
2 football
etc, and JOIN it appropriately in the query.
Do you think it would be helpful to store these relationships between integers and strings in the database itself? As long as you have to store these relationships, it makes sense to store it close to your data (in the database) instead of in your code where it can get lost. If you use this solution, this would make the integer a foreign key to values in another table. You store integers in another table, say sports, with sport_id and sport, and join them as part of your query.
Instead of SELECT * FROM my_table you would SELECT * from my_table and use the appropriate join. If not every row in your main column has a corresponding sport, you could use a left join, otherwise selecting from both tables and using = in the where clause is probably sufficient.
definitely have the DB hold the string values. I am not a DB expert by any means, but I would recommend that you create a table that holds the strings and their corresponding integer values. From there, you can define a relationship between the two tables and then do a JOIN in the select to pull the string version of the integer.
tblSport Columns
------------
SportID int (PK, eg. 12)
SportName varchar (eg. "Tennis")
tblFriend Columns
------------
FriendID int (PK)
FriendName (eg. "Joe")
LikesSportID (eg. 12)
In this example, you can get the following result from the query below:
SELECT FriendName, SportName
FROM tblFriend
INNER JOIN tblSport
ON tblFriend.LikesSportID = tblSport.SportID
Man, it's late - I hope I got that right. by the way, you should read up on the different types of Joins - this is the simplest example of one.