i'm trying to convert this MsSQL to MySQL any idea how this can be done?
WITH Hierarchy(id, ciid1, name, parent, myLevel)
AS (SELECT id,
ciid1,
name,
parent,
0 AS myLevel
FROM cities_new c
WHERE c.id = 2222
UNION ALL
SELECT c.id,
c.ciid1,
c.name,
c.parent,
ch.myLevel + 1
FROM cities_new c
INNER JOIN Hierarchy ch
ON c.parent = ch.ciid1)
SELECT count(id) AS total
FROM hotels_new
WHERE id NOT IN( 69912, 70717, 75347 )
AND ciid IN(SELECT id
FROM Hierarchy)
Related
I would like to seek the advice of some sql experts.
I wrote sql statement for getting authors names from staff and alumni table. Some author's name will be in both tables. So the logic is if the author name is in staff, use that otherwise look for alumni table.
Here is my sql statement, seems fine but it is showing same author name from both staff and alumni table.
SELECT DISTINCT AP.Author_name, P.people_id, P.Name, P.Journal_name, AP.Author_sortorder FROM `Paper_Author` AS AP LEFT JOIN `People` AS P ON ( AP.Author_id = P.people_id ) WHERE AP.Paper_id =3838
UNION
SELECT DISTINCT AN.Author_name, N.People_id, N.Name, N.Journal_name, AN.Author_sortorder FROM `Paper_Author` AS AN LEFT JOIN `Alumni` AS N ON ( AN.Author_id = N.People_id ) WHERE AN.Paper_id =3838 ORDER BY Author_sortorder LIMIT 0 , 30
Result:
people_id-- Author_name-- Journal_name--
1 Name1 A1
2 Name2 B1
3 Name3 C1
3 Name3 C1
4 Name4 D
4 Name4
Expected Result :
people_id-- Author_name-- Journal_name--
1 Name1 A1
2 Name2 B1
3 Name3 C1
4 Name4 D
This can probably be solved by an additional select using the original result as a subquery
SELECT DISTINCT * FROM (
SELECT DISTINCT AP.Author_name, P.people_id, P.Name, P.Journal_name, AP.Author_sortorder FROM `Paper_Author` AS AP LEFT JOIN `People` AS P ON ( AP.Author_id = P.people_id ) WHERE AP.Paper_id =3838
UNION
SELECT DISTINCT AN.Author_name, N.People_id, N.Name, N.Journal_name, AN.Author_sortorder FROM `Paper_Author` AS AN LEFT JOIN `Alumni` AS N ON ( AN.Author_id = N.People_id ) WHERE AN.Paper_id =3838 ORDER BY Author_sortorder LIMIT 0 , 30
);
The difficulty with this problem is that you might need information from either the People or Alumni tables. We would like to just join to a single table containing the right information. Much of the complexity of the below query is in creating a table which contains the right metadata for each person.
SELECT
pa.Author_name,
pa.Author_sortorder,
t1.people_id,
t1.Name,
t1.Journal_name
FROM Paper_Author pa
LEFT JOIN
(
SELECT people_id, Name, Journal_name, 0 AS source
FROM People
UNION ALL
SELECT people_id, Name, Journal_name, 1
FROM Alumni
) t1
ON pa.Author_id = t1.people_id
INNER JOIN
(
SELECT people_id, MIN(source) AS source
FROM
(
SELECT people_id, 0 AS source
FROM People
UNION ALL
SELECT people_id, 1
FROM Alumni
) t
GROUP BY people_id
) t2
ON t1.people_id = t2.people_id AND
t1.source = t2.source
WHERE
pa.Paper_id = 3838;
I have three tables:
customers: id, name
contracts_jewels: id, customer_id, paid, transferred, final_date
contracts_objects: id, customer_id, paid, transferred, final_date
As you see, the structure of the last two tables is the same.
The "paid" and the "transferred" fields contain the value 0 or 1.
What I need is to make a query which should return all the clients (no matter if they have contracts or not), and for each client:
id, name, count_contracts_all, count_contracts_active
where:
count_contracts_all would mean the sum of [SELECT COUNT( * ) FROM
contracts_jewels WHERE customer_id=3 (for example)] and [SELECT
COUNT( * ) FROM contracts_objects WHERE customer_id=3 (for example)]
count_contracts_active would mean the sum of [SELECT COUNT( * ) FROM
contracts_jewels WHERE customer_id=3 AND final_date>=Now() AND paid=0
AND transferred=0] and [SELECT COUNT( * ) FROM contracts_objects WHERE
customer_id=3 AND final_date>=Now() AND paid=0 AND transferred=0]
Any idea? Would you please help me? Thank you!
You can count the contracts separately and then just join them up to the customers:
SELECT
c.id,
COALESCE(oc.active_count,0) + COALESCE(jc.active_count,0) as count_contracts_active,
COALESCE(oc.total_count,0) + COALESCE(jc.total_count,0) as count_contracts_all
FROM customers c
LEFT JOIN (
SELECT
customer_id
COUNT(*) as total_count,
COUNT(IF(final_date>=Now() AND paid=0 AND transferred=0,1,NULL)) as active_count
FROM contracts_jewels
GROUP BY customer_id
) as oc ON oc.customer_id = c.id
LEFT JOIN (
SELECT
customer_id
COUNT(*) as total_count,
COUNT(IF(final_date>=Now() AND paid=0 AND transferred=0,1,NULL)) as active_count
FROM contracts_objects
GROUP BY customer_id
) as jc ON jc.customer_id = c.id
One fast solution I can think of right now is:
SELECT COUNT(`temp_table`.*) FROM (
SELECT * FROM contracts_jewels WHERE customer_id=3 UNION ALL
SELECT * FROM contracts_objects WHERE customer_id=3) AS `temp_table`
AND
SELECT COUNT(`temp_table`.*) FROM (
SELECT * FROM contracts_jewels WHERE customer_id=3 AND final_date>=Now() AND paid=0 AND transferred=0 UNION ALL
SELECT * FROM contracts_objects WHERE customer_id=3 AND final_date>=Now() AND paid=0 AND transferred=0) AS `temp_table`
You can join each of those tables twice and add their corresponding COUNTs in your result:
SELECT
c.id,
(COUNT(cj1.id)+COUNT(co1.id)) AS count_contracts_all,
(COUNT(cj2.id)+COUNT(co2.id)) AS count_contracts_active
FROM
customers c
LEFT OUTER JOIN contracts_jewels cj1 ON c.id = cj1.customer_id
LEFT OUTER JOIN contracts_objects co1 ON c.id = co1.customer_id
LEFT OUTER JOIN contracts_jewels cj2 ON
c.id = cj2.id AND
cj2.final_date >= NOW() AND
cj2.paid = 0 AND
cj2.transferred = 0
LEFT OUTER JOIN contracts_object co2 ON
c.id = co2.id AND
co2.final_date >= NOW() AND
co2.paid = 0 AND
co2.transferred = 0
GROUP BY c.id
Note: I haven't run this, but hopefully it sets you in the right direction.
simple solution:
SELECT SUM(c) FROM (
SELECT COUNT(1) as c FROM `tbl1` where ...
UNION
SELECT COUNT(1) as c FROM tbl2 where ...
UNION
SELECT COUNT(1) as c FROM tbl3 where ...
) al
How can i redo the following query to use only JOINs instead of the nested query?
SELECT SUM(allqty) AS allqty
,COUNT(*) AS orders
FROM (SELECT SUM(S.Qty) AS allqty
FROM data_intra.yw1_ordersheet S
INNER JOIN data_intra.productdata P ON P.productid=S.productid
WHERE P.eCode LIKE (SELECT eCode
FROM data_intra.productdata
WHERE productid=1001)
GROUP BY S.OrderPO) as A;
Here are 2 guesses. Both use IN() instead of LIKE()
This will produce one row for each S.OrderPO
SELECT
SUM(S.Qty) AS allqty
, S.OrderPO
FROM data_intra.yw1_ordersheet S
INNER JOIN data_intra.productdata P
ON P.productid = S.productid
WHERE P.eCode IN (
SELECT
eCode
FROM data_intra.productdata
WHERE productid = 1001
)
GROUP BY
S.OrderPO
;
This will produce one row, counting the distinct number of S.OrderPO
SELECT
SUM(S.Qty) AS allqty
, COUNT(DISTINCT S.OrderPO) AS orders
FROM data_intra.yw1_ordersheet S
INNER JOIN data_intra.productdata P
ON P.productid = S.productid
WHERE P.eCode IN (
SELECT
eCode
FROM data_intra.productdata
WHERE productid = 1001
)
;
I am creating an online shop where people can upload lessons.
My tables structure for this is
products - (contains basic lesson information)
p_tags - id|productid|tag - (contains all tags related to a product)
p_subjects - id|subjectid|productid - (contains all subjects related to a product)
p_years - id|yearid|productid - (contains all years related to a product)
p_types - id|typeid|productid - (contains all subjects related to a product)
subjects - id|name - (contains all subjects links to p_subjects)
resourcetypes - id|name - (contains all product types links to p_types)
years - id|name - (contains all years links to p_years)
What I am trying to do is write a query that can generate a relevance score based on user search criteria. This is what I have so far:
SELECT
IFNull(a.matchedTags,0) AS matchedtags,
a.title,
IFNull(b.matchedSubjects,0) AS matchedsubjects,
IFNull(c.matchedYears,0) AS matchedyears,
IFNull(d.matchedTypes,0) AS matchedtypes
FROM
(
SELECT
z.*,
COUNT(*) AS matchedTags
FROM products z
INNER JOIN p_tags pt ON pt.productid = z.id
WHERE
pt.tag IN('foo','test')
GROUP BY z.id
HAVING COUNT( * ) > 0
) as a
LEFT JOIN (
SELECT
y.*,
COUNT(*) AS matchedSubjects
FROM products y
WHERE
3 IN (SELECT subjectid FROM p_subjects m WHERE m.productid = y.id)
GROUP BY y.id
HAVING COUNT( * ) > 0
) as b ON b.id=a.id
LEFT JOIN (
SELECT
x.*,
COUNT(*) AS matchedYears
FROM products x
WHERE
1 IN (SELECT yearid FROM p_years n WHERE n.productid = x.id)
GROUP BY x.id
HAVING COUNT( * ) > 0
) as c ON c.id=b.id
LEFT JOIN (
SELECT
w.*,
COUNT(*) AS matchedTypes
FROM products w
WHERE
1 IN (SELECT id FROM p_types o WHERE o.productid = w.id)
GROUP BY w.id
HAVING COUNT( * ) > 0
) as d ON d.id=c.id
The query runs fine but will only match a product if the previous criteria is met. I.e if a product has a tag 'foo' then it will then gain a value for number of subjects matched as well. If the product does not contain a tag it will return 0 for all following JOINS.
I'm guessing I'm using the wrong kind of join and have looked into OUTER JOIN using LEFT AND RIGHT then UNION but don't know how to slip this into this code and whether it would work anyway.
Thanks in advance
What an idiot!! I was joining the joins on top of each other so it was only adding to the criteria above. I have changed it now and working sweeet!!
SELECT
g.title,
g.id,
IFNull(a.matchedTags,0) AS matchedtags,
IFNull(b.matchedSubjects,0) AS matchedsubjects,
IFNull(c.matchedYears,0) AS matchedyears,
IFNull(d.matchedTypes,0) AS matchedtypes
FROM
(SELECT id,title FROM products) as g
LEFT JOIN (
SELECT
z.*,
COUNT(*) AS matchedTags
FROM products z
INNER JOIN p_tags pt ON pt.productid = z.id
WHERE
pt.tag IN('test')
GROUP BY z.id
) as a on a.id=g.id
LEFT JOIN (
SELECT
y.*,
COUNT(*) AS matchedSubjects
FROM products y
WHERE
5 IN (SELECT subjectid FROM p_subjects m WHERE m.productid = y.id)
GROUP BY y.id
) as b ON b.id=g.id
LEFT JOIN (
SELECT
x.*,
COUNT(*) AS matchedYears
FROM products x
WHERE
1 IN (SELECT yearid FROM p_years n WHERE n.productid = x.id)
GROUP BY x.id
) as c ON c.id=g.id
LEFT JOIN (
SELECT
w.*,
COUNT(*) AS matchedTypes
FROM products w
WHERE
1 IN (SELECT id FROM p_types o WHERE o.productid = w.id)
GROUP BY w.id
) as d ON d.id=g.id
I want to do this query:
SELECT *
FROM user k
INNER JOIN (
SELECT id, tagName, b.guid, name, owner, publicKey
FROM noteTags a
INNER JOIN (
SELECT *
FROM note
ORDER BY guid
LIMIT 0 , 12
)b ON a.guid = b.guid ORDER BY b.id DESC
)l ON k.owner = l.owner
But I want it to return DISTINCT b.guids.
Structure of the tables:
note
|
|=id
|=name
|=guid
|=owner
|=publicKey
noteTags
|
|=guid
|=tagName
user
|
|=owner
|=username
|=auth
Basically I want to select ALL data (with the limit on the deeper inner join) and return DISTINCT guids
Thanks!
Here's my initial answer,
SELECT *
FROM note a
INNER JOIN user b
ON a.owner = b.owner
INNER JOIN notetags c
ON a.guid = b.guid
INNER JOIN
(
SELECT guid, MAX(tagName) maxTag
FROM notetags
GROUP BY guid
) d ON c.guid = d.guid AND
c.tagName = d.maxTag
How about:
SELECT *
FROM user k
INNER JOIN (
SELECT id, tagName, b.guid, name, owner, publicKey
FROM noteTags a
INNER JOIN (
select id, name, MIN(guid) as guid, owner, publicKey
FROM note
GROUP BY guid
LIMIT 0 , 12
)b ON a.guid = b.guid ORDER BY b.id DESC
)l ON k.owner = l.owner