I am trying to get a SQL code but can't really figure out how to do it so I will explain what I want.
I have 4 tables called Person, Customer, Adres and Store. Now I have to show each customer NAMES which lives in the same city as where there is a Store. So First I figured out which persons are customers by:
SELECT person_name
FROM person
WHERE person_id IN
(SELECT Person_Person_Id
FROM customer);
Which stores are in which city:
SELECT Store_name, adres_city
FROM store s, adres a
WHERE s.Adres_Adres_Id = a.adres_id;
Note that person_person_id is the same as person_id just as a fk.
I am stuck at this code and don''t know how to go further from here. My column name of table adres = adres_city.
Okay, if I realised what do you want, try to do this:
select --distinct
b.Adres_City,
a.person_id
from
dbo.Person a
join dbo.Adres b on a.adres_adres_id = b.Adres_Id
join dbo.Customer c on a.person_id = c.Person_Person_Id
join dbo.Store d on b.Adres_Id = d.Adres_Adres_Id
If you are not sure, that all your keys in tables are uniq, uncomment --distinct in the first string.
Or, if you are want to know statistics among your cities, do this:
select
b.Adres_City,
count(distinct a.person_id) as cnt
from
dbo.Person a
join dbo.Adres b on a.adres_adres_id = b.Adres_Id
join dbo.Customer c on a.person_id = c.Person_Person_Id
join dbo.Store d on b.Adres_Id = d.Adres_Adres_Id
group by b.Adres_City
Please let me know, if it will help you.
Update1:
select --distinct
b.Adres_City,
a.person_id
from
dbo.Person a
join dbo.Adres b on a.adres_adres_id = b.Adres_Id
join dbo.Customer c on a.person_id = c.Person_Person_Id
where
b.Adres_City in (
select y.Adres_City
from dbo.Store x join dbo.Adres y on y.Adres_Id = x.Adres_Adres_Id
)
Related
I have bd hf3 and 5 tables there:
active_preset with columns (id , preset_id)
preset with columns (id , birja_id, trend_id, fractal, interval_up)
birja with columns (id , name)
trend with columns (id , name)
uq_active_preset with columns (id , birja, trend, fractal, interval_up)
In table preset I have a few records. Some of them are in table active_preset by foreign key preset_id. In table active_preset a few records exist once , a few more than once.
I need to update table uq_active_preset with records from table active_preset disregarding repetitions of records if they are present.
I did query from active_preset and it works good:
SELECT
b.name AS birja, p.fractal AS fractal , tre.name AS trend, p.interval_up AS interval_up
FROM hf3.active_preset AS ap
INNER JOIN hf3.preset AS p on p.id = ap.preset_id
INNER JOIN hf3.birja AS b on b.id = p.birja_id
INNER JOIN hf3.trend AS tre on tre.id = p.trend_id
GROUP BY b.name, p.fractal, tre.name, p.interval_up
HAVING COUNT(*) >= 1
But I don't know how to update uq_active_preset
I tried this and it returns syntax error:1064 :
UPDATE hf3.uq_active_preset uap SET
uap.birja = st.birja ,
uap.fractal = st.fractal,
uap.trend = st.trend,
uap.interval_up = st.interval_up,
FROM (SELECT b.name AS birja, p.fractal AS fractal , tre.name AS trend, p.interval_up AS interval_up
from hf3.active_preset AS ap
INNER JOIN hf3.preset AS p on p.id = ap.preset_id
INNER JOIN hf3.birja AS b on b.id = p.birja_id
INNER JOIN hf3.trend AS tre on tre.id = p.trend_id
GROUP BY b.name, p.fractal, tre.name, p.interval_up
HAVING COUNT(*) >= 1
) st
when you make an update using from is like you join the updated table with your query result. So, you need also a where statement in order to tell where those two are connected. Also, don't use alias of your updated table on set statement.
You need something like that:
UPDATE hf3.uq_active_preset uap SET birja=st.birja,fractal=st.fractal,trend=st.trend,interval_up=st.interval_up
FROM (SELECT b.name AS birja, p.fractal AS fractal , tre.name AS trend, p.interval_up AS interval_up
from hf3.active_preset AS ap
INNER JOIN hf3.preset AS p on p.id = ap.preset_id
INNER JOIN hf3.birja AS b on b.id = p.birja_id
INNER JOIN hf3.trend AS tre on tre.id = p.trend_id
GROUP BY b.name, p.fractal, tre.name, p.interval_up
HAVING COUNT(*) >= 1
) st
where uap.fkey=st.fkey
Yes, this is an assignment. So the task was to output two columns of 'first name' and 'last name' with conditions:
-A u (B ∩ -C ∩ -(A ∩ -( B u D)))
A: All consumers that didn't shop on Monday and Friday
(time_by_day.the_day)
B: All consumers who bought 'Non-Consumable'
(product_class.product_family)
C: All consumers who bought more than 10 items
(sales_fact_1997.unit_sales) at one time (sales_fact_1997.time_id)
D: Female consumers from Canada (consumer.gender, consumer.country)
This is what I got so far
SELECT
c.fname,
c.lname
FROM
customer AS c
INNER JOIN sales_fact_1997 AS s ON c.customer_id = s.customer_id
INNER JOIN time_by_day AS t ON s.time_id = t.time_id
INNER JOIN product AS p ON s.product_id = p.product_id
INNER JOIN product_class AS pc ON p.product_class_id = pc.product_class_id
Where
NOT t.the_day in ('Monday', 'Friday') OR
(
pc.product_family = 'Non-Consumable' AND
NOT SUM(s.unit_sales) > 10 AND
NOT (
t.the_day in ('Monday', 'Friday') AND
NOT (
pc.product_family = 'Non-Consumable' OR
(c.country = 'Canada' AND c.gender = 'F')
)
)
)
GROUP BY concat(c.customer_id, s.time_id)
That ended up with an error
#1111 - Invalid use of group function
But I don't know which part of the code is wrong. I'm pretty sure that it's probably the WHERE part. But I don't know what I did wrong.
Condition C is where I'm really struggling. I manage just fine making a query of C
SELECT
t.time_id,
c.customer_id,
c.fullname,
round(SUM(s.unit_sales),0) as tot
FROM
customer as c
INNER JOIN sales_fact_1997 as s ON c.customer_id = s.customer_id
INNER JOIN time_by_day as t on s.time_id=t.time_id
GROUP BY concat(c.customer_id, s.time_id)
ORDER BY c.customer_id, t.time_id
But trying to incorporate it into the main code is hard for me.
Reading online I assume that I should probably use HAVING instead of WHERE.
I would really appreciate it if someone can point me in the right direction.
This is the database that I used.
C: All consumers who bought more than 10 items
(sales_fact_1997.unit_sales) at one time (sales_fact_1997.time_id)
You should use COUNT not SUM.
SELECT time_id,
count(*)
FROM sales_fact_1997
GROUP BY time_id
HAVING COUNT(*)>=10 ;
count(*) is not needed, I let just to show the results
Can you try if it helps:
SELECT c.lname,
c.fname
FROM customer c
INNER JOIN
(
SELECT time_id,customer_id,product_id
FROM sales_fact_1997
GROUP BY time_id,customer_id,product_id
HAVING COUNT(*)>=10
) as s on c.customer_id=s.customer_id
INNER JOIN
(
SELECT time_id,the_day
FROM time_by_day
WHERE the_day
NOT IN ('Monday','Friday')
) as t on s.time_id=t.time_id
INNER JOIN
(
SELECT product_family,product_id
FROM product_class
INNER JOIN product
on product_class.product_class_id=product.product_class_id
WHERE product_family='Non-Consumable'
) pc on s.product_id=pc.product_id
where c.country='Canada' and c.gender ='F' ;
I have this problem. I need to combine data with the same id in one column. The data are separated with ','. I use group_concat but the result is that it combines all. What I need is for example:
But the result is:
my code
SELECT A.bookId,A.bookDate, A.serviceDate, A.bookTime,A.status, GROUP_CONCAT(C.serviceItemId
SEPARATOR ',') AS Servis, B.custId, B.custFname, B.custLname,B.custContact, B.custEmail, B.gender
FROM booking A
JOIN booking_service C on A.bookId = C.bookId
JOIN customer B ON B.custId =
A.cust_fk WHERE A.cust_fk = 4
ORDER BY A.bookId
Can someone help me?
Why not group_concat the values in a sub-query and then join it to your main result set:
SELECT A.bookId,
A.bookDate,
A.serviceDate,
A.bookTime,
A.status,
d.Servis,
B.custId,
B.custFname,
B.custLname,
B.custContact,
B.custEmail,
B.gender
FROM (
SELECT bookId,
GROUP_CONCAT(serviceItemId SEPARATOR ',') AS Servis
FROM booking_service
GROUP BY bookId
) d
JOIN booking A ON a.bookID = d.bookID
JOIN booking_service C on A.bookId = C.bookId
JOIN customer B ON B.custId = A.cust_fk WHERE A.cust_fk = 4
ORDER BY A.bookId
You need to use GROUP BY with GROUP_CONCAT if you want to limit the results to, for example, a single bookId.
You can see what I exactly mean on the image below.
I want to create new column "Bill To This Company" and get the company name from BillToCustomerID
Could be you need a self join
select a.customerId, a.CustomerName, a.BillToCustomerId, b.CustmerName
from my_table a
inner join my_table b on a.BillToCustomerId = b.customerId
Just self-join on the table and give that CustomerName an alias
select
c.CustomerId,
c.CustomerName,
c.BillToCustomerId,
b.CustomerName as "Bill To This Company"
from Customer c
left join Customer b on (b.CustomerId = c.BillToCustomerId)
Seems you need subquery :
select c.*,
(select c1.CustomerName
from Customer c1
where c1.BillToCustomerId = c.BillToCustomerId
order by c1.customerid
limit 1
) as BilltoThisCompany
from Customer c;
update tableName as t1 join tableName as t2 on t1.BillToCustomerID=t2.CustomerId
set t1.`Bill To This Company` = t2.customerName;
I am joining multiple tables into a single query. I need to do a partial match on values in an IN statement. Here is an example.
SELECT DISTINCT
am.id AS id,
am.flagged AS flagged,
am.name AS name,
am.type AS type,
am.file AS file,
am.s3_tag AS s3_tag,
am.low_s3_tag AS low_s3_tag
FROM accounts_media am
LEFT JOIN accounts_location_media alm ON am.id = alm.media_id
LEFT JOIN accounts_location al ON al.id = alm.location_id
LEFT JOIN accounts_person_media apm ON am.id = apm.media_id
LEFT JOIN accounts_person ap ON ap.id = apm.person_id
LEFT JOIN accounts_event_media_record aemr ON am.id=aemr.media_id
LEFT JOIN accounts_medianote_media_record amma ON am.id=amma.media_id
LEFT JOIN accounts_medianote amn ON amma.medianote_id=amn.id
WHERE
am.account_id = '1234'
AND am.flagged = FALSE
AND ('Da' IN (SELECT first_name FROM accounts_person WHERE account_id = '1234')
AND ('Rob' IN (SELECT first_name FROM accounts_person WHERE account_id = '1234')
In the
AND ('Da' IN (SELECT first_name FROM accounts_person WHERE account_id = '1234')
statement there are values that say 'Dan', 'Daniel', etc. in the table. There is also 'Rob' and 'Robert'. I need that statement to make sure and name that contains 'Da' AND any name that contains 'Rob' from that table. Is there a way to do this?
So a record can be linked to multiple people in the accounts_person table. So lets say I have three records.
Record One: A person named Dan is attached to the record.
Record Two: A person named Robert is attached to the record.
Record Three: A person named Dan and a person named Robert are attached to the record.
I want the query to only return Record Three because it has the match of 'Da' and 'Rob'.
Try this:
WHERE
am.account_id = '1234'
AND am.flagged = FALSE
-- AND ( ap.first_name LIKE '%Da%' OR ap.first_name LIKE '%Rob%')
AND EXISTS
( SELECT 1
FROM accounts_person apx
WHERE apx.first_name LIKE '%Da%'
AND apx.account_id = am.account_id
)
AND EXISTS
( SELECT 1
FROM accounts_person apy
WHERE apy.first_name LIKE '%Rob%'
AND apy.account_id = am.account_id
)
I'm not sure, but I think you want a like statement, with a wild card after the Da.
SELECT DISTINCT
am.id AS id,
am.flagged AS flagged,
am.name AS name,
am.type AS type,
am.file AS file,
am.s3_tag AS s3_tag,
am.low_s3_tag AS low_s3_tag
FROM accounts_media am
LEFT JOIN accounts_location_media alm ON am.id = alm.media_id
LEFT JOIN accounts_location al ON al.id = alm.location_id
LEFT JOIN accounts_person_media apm ON am.id = apm.media_id
LEFT JOIN accounts_person ap ON ap.id = apm.person_id
LEFT JOIN accounts_event_media_record aemr ON am.id=aemr.media_id
LEFT JOIN accounts_medianote_media_record amma ON am.id=amma.media_id
LEFT JOIN accounts_medianote amn ON amma.medianote_id=amn.id
WHERE
am.account_id = '1234'
AND am.flagged = FALSE
AND (accounts_person.first_name like '%Da%'
OR accounts_person.first_name like '%Rob%')
AND accounts_person.account_id = '1234'