I have this query that works as I need. However I would like to have a column showing number of times a record repeats.
The query:
SELECT total.Total, subqry.Company AS Supplier, company.Company AS Customer, purchase_details.CompanyID,
product.Description1, purchase_details.PurchaseID, purchase_details.PurchaseCreated,
purchase_details.Completed, purchase_details.OriginalOrd
FROM purchase_details
LEFT JOIN product ON purchase_details.PartNumber = product.PartNumber
LEFT JOIN orders ON purchase_details.OriginalOrd = orders.OrderID
LEFT JOIN contact ON orders.ContactLinkID = contact.ID
LEFT JOIN company ON contact.LinkID = company.LinkID
LEFT JOIN (SELECT company.Company, purchase_details.CompanyID FROM company
LEFT JOIN purchase_details ON company.ID = purchase_details.CompanyID)
AS subqry ON purchase_details.CompanyID = subqry.CompanyID
LEFT JOIN (SELECT OriginalOrd, count(DISTINCT CompanyID) AS Total FROM purchase_details
GROUP BY OriginalOrd) AS total ON purchase_details.OriginalOrd = total.OriginalOrd
WHERE purchase_details.Completed = $show AND
(subqry.Company LIKE :search
OR company.Company LIKE :search
OR product.Description1 LIKE :search
OR purchase_details.PartNumber LIKE :search
OR purchase_details.PurchaseID LIKE :search
OR purchase_details.OriginalOrd LIKE :search)
GROUP BY PurchaseID
The company id column returns:
504
1739
504
1389
504
I would like to return the info below so ideally in a join:
504 | 3
1739 | 1
504 | 3
1389 | 1
504 | 3
I will use this column in the php application to trigger other functions.
Thanks in advance
Add company_id to the GROUp BY list after PurchaseID and add another column count(DISTINCT company_id) company_count to the select.
SELECT
....//other columns
count(DISTINCT purchase_details.CompanyID) company_count
FROM
...//rest of queries
GROUP BY purchase_details.CompanyID,PurchaseID
;
This bit looks odd...
SELECT c.Company
, pd.CompanyID
FROM company c
LEFT
JOIN purchase_details pd
ON c.ID = pd.CompanyID
You're selecting no information from purchase_details that's not already present in company. So why bother?
Also, what might ":search" actually look like?
use group by company_id
select count(company_id) as c
from table_name
group by company_id;
Related
I'm new to this, so I know I'm missing something simple, but I can't figure it out. I'm trying to join 3 tables together and I've got it working with 2 joins, but when combined in the same query, there ends up being an error.
My 3 tables are:
TBL_Authors
Author_ID
Author_Name
TBL_Publishers
Publisher_ID
Publisher_Name
TBL_Books
Title
Author_ID
Publisher_ID
ISBN
Genre
Price
Cost
Rating
What I have that isn't working:
$query = 'SELECT * FROM TBL_PUBLISHERS
JOIN TBL_BOOKS ON TBL_PUBLISHERS.Publisher_ID = TBL_BOOKS.Publisher_ID
SELECT * FROM TBL_AUTHORS
JOIN TBL_BOOKS ON TBL_AUTHORS.Author_ID = TBL_BOOKS.Author_ID
ORDER BY TBL_BOOKS.Title ASC;';
This query assumes that each book was published.
SELECT
*
FROM
TBL_Books b
INNER JOIN TBL_Publishers p ON b.Publisher_ID = p.Publisher_ID
INNER JOIN TBL_Authors a ON b.Author_ID = a.Author_ID
ORDER BY
b.Title
Book will always have an Author, but not necessarily a Publisher, if it's not published. If you need to fetch all the books irrespective of whether published or not, you will have to change INNER join on TBL_Publishers to LEFT.
This Query Will show you the result of all details of book, publisher name, author name.
SELECT
t1.* , t2.Publisher_Name , t3.Author_Name
FROM
TBL_Books as t1
INNER JOIN TBL_Publishers as t2 ON t1.Publisher_ID = t2.Publisher_ID
INNER JOIN TBL_Authors as t3 ON t1.Author_ID = t2.Author_ID
ORDER BY
t1.Title
Check This and update if this query helps you.
I have Three tables look like below:
test_case
id project_id requirement_id
1 5 11,12
2 4 12,13
3 5 10,12
task_categories (refenced with test_case table with requirement_id)
id name
10 ten
11 eleven
12 twelve
13 thirtien
projects (refenced with test_case table with project_id)
id name
4 P1
5 P2
Now,i wanna make a query with where condition by passing parameter like project_id=5 and want the output look like below:
id project_name requirement_name
1 P2 eleven,twelve
3 P2 ten,twelve
I tried the following code in my model:
public function display($project_id) {
$sql = "
SELECT i.id as id, i.project_id as project_id, requirement_id, GROUP_CONCAT(c.name SEPARATOR '\n <br>*') as req_name, p.id as projects_id FROM test_case i, task_categories c, projects p
WHERE FIND_IN_SET(c.id, i.requirement_id) AND i.project_id = $project_id
GROUP BY i.id";
$query = $this->db->query($sql);
return $query->result();
}
Your current approach has a problem because it results in selecting non aggregate columns while using GROUP BY. Here is a query which should work:
SELECT t1.id,
COALESCE(t2.project_name, 'NA') AS project_name,
t1.req_name
FROM
(
SELECT t.id,
t.project_id,
GROUP_CONCAT(tc.name SEPARATOR '\n <br>*') AS req_name
FROM test_case t
INNER JOIN task_categories tc
ON FIND_IN_SET(tc.id, t.requirement_id) > 0
GROUP BY t.id, t.project_id
) t1
LEFT JOIN projects t2
ON t1.project_id = t2.id
In the above query, I join test_case and task_categories together in a subquery to obtain all combinations of id, project_id, and their requirements list. Then I use another LEFT JOIN to bring in the project name from the projects table.
I am having an issue where I want to join several columns by an id.
My first table looks like this:
submitter_id reviewer_id processor_id
75 34 91
The table that I want to join looks like this:
id first_name last_name
75 Bob Smith
34 Albert McDonald
91 Joe Blo
I am trying to create a query that will look at each id in my first table and then get the first and last name's for each id.
For example, a query that does this should return something like:
[
75 => "Bob Smith",
34 => "Albert McDonald",
91 => "Joe Blo"
];
Can anybody help me construct a query that can accomplish this? Thanks!
Join the same table 3 times with different alias names
select t1.submitter_id, t1.reviewer_id, t1.processor_id,
t2.first_name as submitter_firstname, t2.last_name as submitter_lastname,
t3.first_name as reviewer_firstname, t3.last_name as reviewer_lastname,
t4.first_name as processor_firstname, t4.last_name as processor_lastname
from firstTable t1
left join namesTable t2 on t1.submitter_id = t2.id
left join namesTable t3 on t1.reviewer_id = t3.id
left join namesTable t4 on t1.processor_id = t4.id
I think what your actually looking for is more like this:
SELECT n.id, CONCAT(n.first_name, ' ', n.last_name)
FROM names n
JOIN ids i
ON n.id = i.submitter_id
OR n.id = i.reviewer_id
OR n.id = i.processor_id
GROUP BY n.id;
This is only doing one join, shows the records with the 2 columns you actually want and restricts so users are only listed 1 time. Also since you probably don't want to return just the ID if the user doesn't have a name setup you don't want a left join.
Edit:
If you need indexes you can make one on submitter_id, reviewer_id, processor_id if the performance is needed for you.
You want all in one resultset, so you could use UNION ALL:
SELECT p.id, CONCAT(p.first_name, ' ', p.last_name) as name
FROM person p
JOIN firstTable f
ON p.id = f.submitter_id
UNION ALL
SELECT p.id, CONCAT(p.first_name, ' ', p.last_name) as name
FROM person p
JOIN firstTable f
ON p.id = f.reviewer_id
UNION ALL
SELECT p.id, CONCAT(p.first_name, ' ', p.last_name) as name
FROM person p
JOIN firstTable f
ON p.id = f.processor_id
I think this is a better approach if you plan to use some conditions only for some group, like where reviewer_id > 100. If not, the Sir. Egole is cleaner.
Assuming that you need one row in the first table to return one row at the result.
SELECT tt.submitter_id , CONCAT(ta.first_name, ' ', ta.last_name) ,
tt.reviewer_id , CONCAT(tb.first_name, ' ', tb.last_name) ,
tt.processor_id , CONCAT(tc.first_name, ' ', tc.last_name)
FROM `transaction` as tt , `names` as ta , `names` as tb , `names` as tc
WHERE tt.submitter_id = ta.id AND
tt.reviewer_id = tb.id AND
tt.processor_id = tc.id
The result would be the 3 ids with the corresponding names in one row per transaction.
I build a query a month ago on a website. It was working fine. But after a month I was informed that the website become very slow to load the page.
When I search for the problem, I found that my query is executing very slow to fetch the data from mysql database. Then I check for the database and found that the 4 tables which I was using by joins, have around 216850, 167634, 64000, 931 rows respectively.
I have already have indexed that tables. So, where I'm lacking. Please help guys.
[Edit]
Table1: user_alert
Records: 216850
DB Type: InnoDB
Indexes: id(primary)
Table2: orders
Records: 167634
DB Type: InnoDB
Indexes: id(primary), order_id, customer_id
Table3: user_registration
Records: 64000 around
DB Type: InnoDB
Indexes: id(primary), email_address
Table4: cities
Records: 931
DB Type: InnoDB
Indexes: id(primary)
Query:
SELECT uas.alert_id, uas.user_id, uas.status, ur.first_name, ur.last_name, ur.email_address, o.order_id,
CASE WHEN ct.city_name IS NULL THEN uas.city_name ELSE ct.city_name END AS city_name
FROM `user_alert` uas
LEFT JOIN orders o ON o.customer_id = uas.user_id
LEFT JOIN user_registration ur ON ur.id = uas.user_id
LEFT JOIN `cities` ct ON ct.city_id = uas.city_id
WHERE uas.status = '1'
GROUP BY uas.user_id
ORDER BY uas.create_date DESC
GROUP BY is used to aggregate values up. For example if you wanted the count of orders by a user you could use COUNT(o.order_id).....GROUP BY uas.user_id. There are multiple orders for each user, but the aggregate function is just counting them here. However if you just select o.order_id when you have a GROUP BY uas.user_id it doesn't know which of the possibly many order_id values to return for that user id.
In this case it possibly doesn't matter as it looks like the order table is the only one where there is multiple rows per use. If you want the latest one you could just use MAX(o.order_id) (assuming that the order_id is assigned is order). But if you wanted the order value it becomes more difficult.
SELECT uas.alert_id, uas.user_id, uas.status, ur.first_name, ur.last_name, ur.email_address, MAX(o.order_id) AS LatestOrderId,
IFNULL(ct.city_name, uas.city_name) AS city_name
FROM `user_alert` uas
LEFT JOIN orders o ON o.customer_id = uas.user_id
LEFT JOIN user_registration ur ON ur.id = uas.user_id
LEFT JOIN `cities` ct ON ct.city_id = uas.city_id
WHERE uas.status = '1'
GROUP BY uas.user_id
ORDER BY uas.create_date DESC
If you wanted the (say) value of the latest order then it becomes more difficult.
SELECT uas.alert_id, uas.user_id, uas.status, ur.first_name, ur.last_name, ur.email_address, Sub1.MaxOrderId AS LatestOrderId, o.order_value
IFNULL(ct.city_name, uas.city_name) AS city_name
FROM `user_alert` uas
LEFT JOIN (SELECT customer_id, MAX(order_id) AS MaxOrderId FROM orders GROUP BY customer_id) Sub1 ON Sub1.customer_id = uas.user_id
LEFT OUTER JOIN orders o ON o.customer_id = Sub1.user_id AND o.order_id = Sub1.MaxOrderId
LEFT JOIN user_registration ur ON ur.id = uas.user_id
LEFT JOIN `cities` ct ON ct.city_id = uas.city_id
WHERE uas.status = '1'
ORDER BY uas.create_date DESC
Or doing a bit of a fiddle based on GROUP_CONCAT
SELECT uas.alert_id, uas.user_id, uas.status, ur.first_name, ur.last_name, ur.email_address,
SUBSTRING_INDEX(GROUP_CONCAT(o.order_id ORDER BY o.order_id DESC), ',', 1) AS LatestOrderId,
SUBSTRING_INDEX(GROUP_CONCAT(o.order_value ORDER BY o.order_id DESC), ',', 1) AS LatestOrderValue,
IFNULL(ct.city_name, uas.city_name) AS city_name
FROM `user_alert` uas
LEFT OUTER JOIN orders o ON o.customer_id = uas.user_id AND o.order_id = Sub1.MaxOrderId
LEFT JOIN user_registration ur ON ur.id = uas.user_id
LEFT JOIN `cities` ct ON ct.city_id = uas.city_id
WHERE uas.status = '1'
GROUP BY uas.user_id
ORDER BY uas.create_date DESC
i have two table. Records and Villas
Records table:
ID, VID (Villa ID), NAME, PRICE
Villas table:
ID, NAME (Villa NAME), PHOTOS etc.
I using this SQL:
SELECT records.id, villa_name AS (SELECT name FROM villas WHERE id = records.vid), records.name
FROM records WHERE records.id = 5
What is wrong ?
Try
SELECT records.id, records.name AS record_name, villas.name AS villa_name FROM records INNER JOIN villas ON records.vid = villas.id WHERE records.id = 5
Edit: Incorporated suggestion from Mark Bannister, below.
You should use JOIN here.
SELECT r.id, r.name, v.name
FROM records r
INNER JOIN villas v ON v.id = r.vid
WHERE records.id = 5;