MySQL - Show latest successful test - mysql

How can I get all the latest successful tests by program? The latest one has the highest Build number and successful are all PASSED and OF CONCERN
My table looks like this (I excluded some columns from the original):
+----+---------+----------------+-------+-----------+---------+
| ID | Test | Program | Build | Result | Tester |
+----+---------+----------------+-------+-----------+---------+
| 1 | 1 | Mag. & Speech | 1825 | PASSED | Dale |
| 2 | 2 | Scr. Reader | 1820 | PASSED | Aadarsh |
| 3 | 2 | Scr. Reader | 1821 | PASSED | Tony |
| 4 | 2 | Scr. Reader | 1824 | PASSED | Tony |
| 5 | 2 | Mag. & Speech | 1820 | PASSED | Colin |
| 6 | 2 | Mag. & Speech | 1821 | FAILED | Dale |
| 7 | 2 | Mag. & Speech | 1822 | OF CONCERN| Tony |
| 8 | 2 | Mag. | 1820 | PASSED | Steven |
| 9 | 3 | Scr. Reader | 1820 | NOT TESTED| Aadarsh |
+----+---------+----------------+-------+-----------+---------+
As a result I would want to get the row (ID) 1,4,7,8. As you can see, no program has more than one of the same test.
Edit:
Added some missing information to the table.
Sadly I don't have the queries anymore, I tried, but I didn't get very far with just Where and Order By.

This query should do the trick
SELECT t3.*
FROM (
SELECT t1.ID,
MAX(t1.Build) as Build
FROM table_name t1
WHERE LOWER(t1.Result) NOT IN( 'n/a', 'not completed', 'not tested' )
GROUP BY t1.Test, t1.Program
) t2
INNER JOIN table_name t3
ON t3.ID = t2.ID
AND t3.Build = t2.Build;
Unfortunately it is a bit complicated due to group by limitations.
Please replace table_name (in 2 places) with proper name

Related

Query to fetch sequences of distinct records with LIMIT and OFFSET

So, my question may be confusing and you may ask what do I mean exactly?
Let's assume I've the following table (contacts) in my database:
+----+----------+-----------+
| id | provider | name |
+----+----------+-----------+
| 1 | MSC | Roger |
| 2 | DLL | Steven |
| 3 | DLL | Pensi |
| 4 | DLL | Kendswill |
| 5 | MSC | Mark |
| 6 | LAPTON | Steffan |
| 7 | MSC | John |
| 8 | MSC | Cori |
| 9 | LAPTON | Jason |
+----+----------+-----------+
I'm looking to fetch for example 3 records, so it must be in a specific sequence - the query should yield a sequence (or sequences) of one record for each provider, distinct ones in each sequence (based on the provider in this example), for example, if the LIMIT set to 4, I should get:
+----+----------+-----------+
| id | provider | name |
+----+----------+-----------+
| 1 | MSC | Roger |
| 4 | DLL | Kendswill |
| 6 | LAPTON | Steffan |
| 7 | MSC | John |
+----+----------+-----------+
And if I would set the LIMIT to 4 and set an OFFSET of 4, now I should get:
+----+----------+--------+
| id | provider | name |
+----+----------+--------+
| 5 | MSC | Mark |
| 2 | DLL | Steven |
| 9 | LAPTON | Jason |
| 8 | MSC | Cori |
+----+----------+--------+
And so on and so forth.
As you may see, it should be consistent and should be organized always in the same way (not a random way).
I've heard about gap and islands, but wonder if someone could shed some light on the subject?
Assign each row that has the same provider with an increasing number. Then you can sort by that number. The rows that have an 1 for each provider will show up first, followed by those with the number two.
select *
from (
select #rn := case when provider = #lastprovider then #rn + 1 else 1 end
, #lastprovider := provider
, #rn as provider_row_num
, provider
, name
from Table1
, (select #rn := 0, #lastprovider := '') init
order by
provider
, id
) sub
order by
provider_row_num
, provider
limit 4
Working example at SQL Fiddle.

How to ROLLUP a SUM over multiple columns on separate tables?

I have 4 tables from which I want to aggregate data using MySQL 5.7.
Projects
+------------+--------+------------------+
| project_id | org_id | name |
+------------+--------+------------------+
| 1 | 1 | Big Project |
| 2 | 1 | Internal Project |
+------------+--------+------------------+
Tasks
+-----------+--------+----------------+------------+
| task_id | org_id | name | project_id |
+-----------+--------+----------------+------------+
| 1 | 1 | Check Work | 1 |
| 2 | 1 | Fix Code | 1 |
| 3 | 1 | Rebuild Office | 2 |
+-----------+--------+----------------+------------+
Resources
+-------------+--------+-------------+-----------+
| resource_id | org_id | first_name | last_name |
+-------------+--------+-------------+-----------+
| 1 | 1 | Alice | Black |
| 2 | 1 | Bob | Smith |
| 3 | 1 | Charlie | White |
+-------------+--------+-------------+-----------+
Task_Details
+-------------+--------+---------+-------------+
| resource_id | org_id | task_id | total_hours |
+-------------+--------+---------+-------------+
| 1 | 1 | 1 | 12 |
| 2 | 1 | 1 | 4 |
| 3 | 1 | 1 | 8 |
| 2 | 1 | 2 | 4 |
| 3 | 1 | 2 | 4 |
| 1 | 1 | 3 | 16 |
+-------------+--------+---------+-------------+
I want to SUM the total_hours, GROUPing by task and project, while still showing the total_hours each employee has individually spent on a task. The output I'm looking for would be something like this
Desired Output
+------------------+----------------+------------+-----------+-------------+
| project_name | task_name | first_name | last_name | total_hours |
+------------------+----------------+------------+-----------+-------------+
| Big Project | Check Work | Alice | Green | 12 |
| Big Project | Check Work | Bob | Smith | 4 |
| Big Project | Check Work | Charlie | Brown | 8 |
| Big Project | Check Work | NULL | NULL | 24 |
| Big Project | Fix Code | Bob | Smith | 4 |
| Big Project | Fix Code | Charlie | Brown | 4 |
| Big Project | Fix Code | NULL | NULL | 8 |
| Big Project | NULL | NULL | NULL | 32 |
| Internal Project | Rebuild Office | Alice | Green | 16 |
| Internal Project | Rebuild Office | NULL | NULL | 16 |
| Internal Project | NULL | NULL | NULL | 16 |
+------------------+----------------+------------+-----------+-------------+
I've managed to create a query that JOINs the relevant tables together, and even managed to GROUP them by project_id, task_id and resource_id. However, adding a WITH ROLLUP statement to the end of my query causes it to fail even though it works without one.
This is my current query:
SELECT
t1.project_name,
t1.task_name,
t2.first_name,
t2.last_name,
SUM(t1.task_hours)
FROM (
SELECT
Projects.project_id,
Projects.name AS project_name,
Tasks.task_id,
Tasks.name AS task_name,
Resources.resource_id,
Task_Details.total_hours AS task_hours
FROM
Projects
RIGHT OUTER JOIN
Tasks
ON
Projects.org_id = Tasks.org_id AND
Projects.project_id = Tasks.project_id
LEFT OUTER JOIN
Task_Details
ON
Task_Details.org_id = Tasks.org_id AND
Task_Details.task_id = Tasks.task_id
LEFT OUTER JOIN
Resources
ON
Resources.org_id = Task_Details.org_id AND
Resources.resource_id = Task_Details.resource_id
WHERE
Projects.org_id = 1
) AS t1
JOIN (
SELECT
resource_id,
first_name,
last_name
FROM
Resources
WHERE
org_id = 1
) AS t2
ON
t2.resource_id = t1.resource_id
GROUP BY
t1.project_id,
t1.task_id,
t1.resource_id;
How can I modify my query such that WITH ROLLUP works?
My SQLFiddle is here, but notably is for MySQL 5.6 rather than 5.7
IMHO, the problem with your query is this: You select some columns which are not in the GROUP BY. That causes some non-sensical values in the columns first_name, last_name, project_name and task_name. However, the sum column is probably correct, isn't it?
This works for me:
SELECT p.name as project_name,
s1.task_name,
first_name,
last_name,
s1.total_hours
FROM (
SELECT
t.project_id,
t.name as task_name,
h.resource_id,
sum(h.total_hours) as total_hours
FROM Task_Details as h
JOIN Tasks as t ON (t.task_id=h.task_id)
GROUP BY t.project_id, t.name, h.resource_id WITH ROLLUP
) AS s1
LEFT JOIN Resources AS r ON (s1.resource_id=r.resource_id)
JOIN Projects AS p ON (p.project_id=s1.project_id);
The nested SELECT does the interesting work, it sums up the total_hours of every resource_id, every task_name and and every project_id. The nesting SELECT then collects the name of every resource and project.
OUTPUT:
+------------------+----------------+------------+-----------+-------------+
| project_name | task_name | first_name | last_name | total_hours |
+------------------+----------------+------------+-----------+-------------+
| Big Project | NULL | NULL | NULL | 32 |
| Big Project | Check Work | Alice | Green | 12 |
| Big Project | Check Work | NULL | NULL | 24 |
| Big Project | Check Work | Bob | Smith | 4 |
| Big Project | Check Work | Charlie | Brown | 8 |
| Big Project | Fix Code | Bob | Smith | 4 |
| Big Project | Fix Code | Charlie | Brown | 4 |
| Big Project | Fix Code | NULL | NULL | 8 |
| Internal Project | NULL | NULL | NULL | 16 |
| Internal Project | Rebuild Office | NULL | NULL | 16 |
| Internal Project | Rebuild Office | Alice | Green | 16 |
+------------------+----------------+------------+-----------+-------------+
Hope this helps.

MySql Update Row and it's "Descendants"

I'm having trouble figuring out how to update the descendants/children of a row.
Example table, named test
+----+--------+------+
| Id | Parent | Val |
+----+--------+------+
| 1 | 0 | |
| 2 | 1 | |
| 3 | 1 | |
| 4 | 1 | |
| 5 | 0 | |
| 6 | 5 | |
| 7 | 6 | |
| 8 | 6 | |
| 9 | 0 | |
+----+--------+------+
What I'd like to have done is, when Val is set to something, update every row that is related to that row. For example, If I ran
UPDATE test SET Val=1 WHERE Id=5;
I want Val in the rows where the Id is 6, 7, and 8, to also be 1.
The best thing I could come up with was
UPDATE test t1
JOIN test t2 ON t1.Id = t2.Parent
JOIN test t3 ON t2.Id = t3.Parent
SET t1.Val=1, t2.Val=1, t3.Val=1 WHERE t1.Id=5;
+----+--------+------+
| Id | Parent | Val |
+----+--------+------+
| 1 | 0 | |
| 2 | 1 | |
| 3 | 1 | |
| 4 | 1 | |
| 5 | 0 | 1 |
| 6 | 5 | 1 |
| 7 | 6 | 1 |
| 8 | 6 | 1 |
| 9 | 0 | |
+----+--------+------+
This gives me what I want, but I'm afraid it's poor practice and it doesn't account for a variable depth. What can I do here? I thought a trigger may have been the answer, but that didn't seem to be possible. I got the error "Can't update table in stored function/trigger because it is already used by statement which invoked this stored function/trigger"
It's pretty awkward to handle this kind of case with MySQL, because MySQL doesn't support recursive queries.
I solve this problem by storing the hierarchy as a transitive closure, instead of the "parent_id" style you're using. See my answer to What is the most efficient/elegant way to parse a flat table into a tree?
Then you can update all descendants of a given node in the heirarchy:
UPDATE test JOIN testclosure AS c ON test.id = c.descendant
SET test.val = 1
WHERE c.ancestor = 5;

SQL INSERT INTO query syntax

I am trying to run an MySQL query to copy over data from an old table (ps__product_review/rate) to a new table (ps_product_comment/grade) based on review ID (id_product_comment). But I am a bit lost on the SQL query, this is what I have but keep getting errors.
INSERT INTO ps_product_comment [(grade)]
SELECT rate
FROM ps__product_review
[WHERE ps__product_review.id_product_comment=ps_product_comment.id_product_comment];
Can anyone help write the correct query?
Edit:Essentially I am trying to populate the Grade column in the new table below.
Old table (ps__product_review)
+--------------------+----------+-----+
| id_product_comment | Comment | Rate|
+--------------------+----------+-----+
| 1 | Good | 2 |
| 2 | Great | 5 |
| 3 | OK | 3 |
| 4 | Brill | 4 |
| 5 | OK | 3 |
| 6 | Average | 2 |
| 7 | Bad | 1 |
+--------------------+----------+-----+
New Table (ps_product_comment)
+--------------------+----------+-------+
| id_product_comment | Comment | Grade |
+--------------------+----------+-------+
| 1 | Good | |
| 2 | Great | |
| 3 | OK | |
| 4 | Brill | |
| 5 | OK | |
| 6 | Average | |
| 7 | Bad | |
+--------------------+----------+-------+
If you want to update table with data from another table, use UPDATE with JOIN
UPDATE ps_product_comment
JOIN ps__product_review
ON ps__product_review.id_product_comment = ps_product_comment.id_product_comment
SET ps_product_comment.grade = ps__product_review.rate;
Remove the square brackets and I think you are missing the JOIN(since you are using that in your where clause):
INSERT INTO ps_product_comment (grade)
SELECT rate
FROM ps__product_review inner join ps_product_comment on
ps__product_review.id_product_comment=ps_product_comment.id_product_comment;

MySQL Newbie - Select all False in One to Many

Devices Network_Card
================== ===========================================
| id | hostname | | id | device_id | ip_address | dns |
================== ===========================================
| 1 | desktop1 | | 1 | 1 | 10.0.0.1 | desktop1 |
| 2 | laptop1 | | 2 | 2 | 10.0.0.2 | laptop1 |
| 3 | laptop2 | | 3 | 2 | 10.0.0.3 | laptop1w |
| 4 | desktop2 | | 4 | 3 | 10.0.0.4 | george |
| .. | ... | | 5 | 4 | 10.0.0.5 | desktop2w |
================== ===========================================
Hi folks, here's my situation. We have a home grown computer inventory with 500+ devices and the db gets populated from different sources. I'm trying to find the discrepancies in this case, so I'm trying to select devices.id where I don't have a DNS record is NOT LIKE the hostname. In this case, it would return devices.id = 3
I haven't done relational db queries in a long time, and my brain can't process the double negatives, so any help would be great.
This query might do it for you:
select d.id, d.hostname, n.dns
from devices d
left join network_card n on d.id = n.device_id
where d.hostname != substring(n.dns, 1, LENGTH(d.hostname))
I'm using substring since I'm not sure how to do a field + wildcard to use within a NOT LIKE expression. Using substring lets you do a straight != comparison.
Update: Thanks to PaparazzoKid for the sqlfiddle at: http://www.sqlfiddle.com/#!2/3a260/1