I have a table in SQLite named Clients:
ID
Name
Hobbies
SubHobbies
1
Anne
sports, fashion
shoes, swimming
2
Max
eating, automative
desserts, cars
I split the Hobbies column using Common Table Expressions (with split() as) :
ID
Name
Hobbies
SubHobbies
1
Anne
sports
shoes, swimming
1
Anne
fashion
shoes, swimming
2
Max
eating
desserts, cars
2
Max
automative
desserts, cars
Now I also want to split the Subhubbies column, which I can do using CTE. The format I want is (Swimming is a subhubby of Sports, shoes-Fashion, desserts-eating and cars-automative) :
ID
Name
Hobbies
SubHobbies
1
Anne
sports
swimming
1
Anne
fashion
shoes
2
Max
eating
desserts
2
Max
automative
cars
There are many clients, hobbies and sub-hobbies in this table so I don't want to do this one by one. Any ideas for splitting and placing them in the right place with queries?
You need to define the Hobbies table:
CREATE TABLE Hobbies (
`Hobby` TEXT,
`SubHobby` TEXT
);
INSERT INTO Hobbies
(`Hobby`, `SubHobby`)
VALUES
('sports', 'swimming'),
('fashion', 'shoes'),
('eating', 'desserts'),
('automative', 'cars');
You should have this table anyway, because otherwise your Clients table is not normalized. Then you run this query against the Clients/Hobbies tables:
SELECT c.ID, c.Name, h.Hobby, h.SubHobby
FROM Clients AS c, Hobbies AS h
WHERE instr(' ' || c.SubHobbies || ',', ' ' || h.SubHobby || ',')
Depending on your data, simple WHERE instr(c.SubHobbies, h.SubHobby) might also do just fine.
Related
I have one table containing rows with information about dealers and unique IDs.
id name
1 dealer1
2 dealer2
The other table contains products which are sometimes available at multiple dealers.
name dealerids
product1 1, 2
product2 2
Now I would like to query all dealers a product is available at, but I don't know how. I tried something like:
SELECT * FROM dealers WHERE id IN (SELECT dealerids FROM products WHERE name = "product1")
which didn't work. I'm in C# and dealerids is based on a string and stored as TEXT in the database. I tried "'1', '2'" and "1, 2", both didn't work for me.
I'm quiet new to SQL so is there a way to achieve what I want using the TEXT datatype?
Well, that's strange way to store the values in a database - as a string separated by commas. But if it's really the case and you can not change this to multiple lines where each record corresponds to one dealer id , you probably can try this:
select * from dealers where exists (select 1 from products where name = "product1" and dealerids like
dealers.id || ',' || '%') or exists
(select 1 from products where name = "product1" and dealerids like '%' || ', ' || dealers.id || ',%')
or exists
(select 1 from products where name = "product1" and dealerids like '%, ' || dealeris.id)
The first clause is taking care of the case where desired delearid is the first one in the string, the second clause is for the case when it's in the middle, and the third one is for the ending id.
A normalized database would look something like this, in your scenario.
// table_dealer
id name
1 dealer1
2 dealer2
// table_product
id title
1 product1
2 product2
//table_associate
id product_id dealer_id
1 1 1
1 2 1
Now I would like to query all dealers a product is available at, but I don't know how. I tried something like
//searching by product_id
select dealer_id from table_associate where product_id = X
Use JOIN query to get data from these 3 tables.
So basically I have this column called Signature inserted in the database
Id = 1
Value = John, Micheal, Sara
Id = 2
Value = Mike, Steve, John
.
.
Now in asp.net I'm not sure how can I do select command and know if the value
John, Micheal, Sara
Has "Micheal" in it
To answer you question:
CHARINDEX() searches for a substring within a larger string, and returns the position of the match, or 0 if no match is found
SELECT * FROM [Table] WHERE CHARINDEX(Signature, 'Michael') > 0
Or
You can just use wildcards in the query (after IF, WHERE or ON):
SELECT * FROM [Table] WHERE Signature LIKE '%' + 'Michael' + '%'
But really you should be storing this data in a separate related table.
No. Don't.
Add a new table with rows for each signature name, and use a row for each signatory. That is the point of relational databases.
1 John
1 Michael
1 Sara
2 Mike
2 Steve
2 John
Or better still, add two new tables - one for the signatories, and one for the relation between that and your initial table
Signatories
1 John
2 Michael
ItemSignatures
ItemID SignatoryID
1 1
1 2
2 1
select *
from Signature
where value like '%Micheal%'
Suppose I have these tables:
person
id name
-- ----
1 dude
2 john
3 doe
...etc
favourite_food
personid food
-------- ------
1 apples
5 apples
5 oranges
And I want to get a list of the names of people who like at least the foods that person 5 likes. Something like below:
SELECT p.name FROM person p
LEFT JOIN favourite_food ff ON ff.personid = p.id
WHERE ff.food = (SELECT food FROM favourite_food WHERE personid = 5)
AND ff.personid <> 5;
Except I have no idea how to specify the 'at least' part. Do I have to create a temporary table or so?
SQL essentially works with sets, so it often helps to reformulate your problem strictly in terms of set theory.
"At least" could be reformulated this way:
If we look only at foods that are favourite foods of person 5, which persons have the same number of favourite foods as person 5?
SELECT name
FROM person
WHERE id IN (SELECT personid
FROM favourite_food
WHERE food IN (SELECT food
FROM favourite_food
WHERE personid = 5)
GROUP BY personid
HAVING COUNT(food) = (SELECT COUNT(food)
FROM favourite_food
WHERE personid = 5)
)
Alternatively, use this reformulation:
We do not want persons who do not like a food that person 5 likes.
Therefore, find all persons for which no food exists that is liked by person 5 but not liked by that person:
SELECT name
FROM person
WHERE NOT EXISTS (SELECT 1
FROM favourite_food AS person5_food
WHERE personid = 5
AND NOT EXISTS (SELECT 1
FROM favourite_food
WHERE personid = person.id
AND food = person5_food.food)
)
(Actually, SQL is based on the relational algebra, and the operation you want is called division.)
I have 2 tables:
Employee_tbl
empid empname empsalary emplocation
----- ------- --------- ------------
1 santhosh 15000 East godavari
2 Srinivas 25000 Westgodavari
3 sandeep 35000 Hyderabad
4 prathap 55000 Hyderabad
5 praveen 45000 West godavari
configuration_tbl
config_id column_name
--------- -----------
1 empid
2 empname
3 empsalary
4 emplocation
When I pass input as config_id it should display the values from that column.
Ex: If I pass config_id then it should display all empname from employee_tbl.
When there is only a limited number of columns I advice you to use a SQL with a case statement. Depending on whether you want to fold numbers into one text field or not, you may need two case columns. Execute immediate is possible but has additional overhead.
Mentor table
------------
name (varchar)
contact (int)
english (boolean)
french (boolean)
german (boolean)
Student table
-------------
name (varchar)
contact (int)
english (boolean)
french (boolean)
german (boolean)
I want to match mentor with student based on the languages, such that for example:
if mentor1 knows english and french, he will be matched with all students that know at least english or french.
mentor1 (english, french)
-------------------------
studentA (english);
studentB (english, french);
studentC (english, german);
studentD (english, french, german)
if mentor2 know german only, he will be matched with all students that know at least german. the students matched can know more than just german.
mentor2 (german)
----------------
studentC (english, german)
studentD (english, french, german)
normally i will just use a bunch of if then else to piece together a sql string but i am using gridview to display the data so i am not sure what can i do.
sample codes and tutorials are alway welcome.
edit: forgot to mention that the mentor table will also have columns such as name and contact. so the output on the gridview should be 1 row per mentor.
Select
m.MentorName
, m.Language
, s.StudentName
from Mentor as m
inner join Student as s
on (m.English = 1 and m.English = s.English)
or (m.french = 1 and m.French = s.French)
or (m.German = 1 and m.German = s.German);
This would be easier if you had your tables structured without field for each language but a record instead
Table: Mentor(MentorName, Language)
Rows:
Mentor1 | English
Mentor2 | Englisn
Mentor2 | French
Do the same for Students and then the query is:
Select
m.MentorName
, m.Language
, s.StudentName
from Mentor as m
inner join Student as s
on m.Language = s.Language
The benefit here is if you add another language, it is purely data entry and no need to change table structure or your code, but that is not always an option.
SELECT m.*, s.name
FROM dbo.Mentor m
JOIN dbo.Student s
ON EXISTS
(
SELECT x.LanguageID
FROM
(
SELECT 1 AS LanguageID WHERE s.english = 1 UNION ALL
SELECT 2 AS LanguageID WHERE s.french = 1 UNION ALL
SELECT 3 AS LanguageID WHERE s.german = 1
) x
INTERSECT
SELECT y.LanguageID
FROM
(
SELECT 1 AS LanguageID WHERE m.english = 1 UNION ALL
SELECT 2 AS LanguageID WHERE m.french = 1 UNION ALL
SELECT 3 AS LanguageID WHERE m.german = 1
) y
)
ORDER BY m.name