EDIT: I think I got it. Will do further test tomorrow and I'll get back to this post. Thanks guys!
I'm trying to query for the last transaction made for each item on tbl_invty that doesn't have the transaction type "Idle" from table tbl_trans. The multiplicity of transactions is confusing me on getting my query right and all I was able to do so far was joining the two tables below on tbl_invty.code=tbl_trans.code. How do I go about this so I could output only rows 2 and 3 from tbl_invty joined with rows 5 and 8 from tbl_trans based on the column code?
tbl_invty
+------+-------------+
| CODE | DESCRIPTION |
+------+-------------+
| 1 | abc |
| 2 | bbb |
| 3 | cdf |
+------+-------------+
tbl_trans
+----------+------+--------+------------+
| TRANS_ID | CODE | TYPE | TRANS_DATE |
+----------+------+--------+------------+
| 1 | 1 | NEW | 2012-09-29 |
| 2 | 1 | UPDATE | 2012-09-30 |
| 3 | 1 | IDLE | 2012-09-30 |
| 4 | 2 | NEW | 2012-09-29 |
| 5 | 2 | UPDATE | 2012-09-30 |
| 6 | 3 | NEW | 2012-09-29 |
| 7 | 3 | UPDATE | 2012-09-30 |
| 8 | 3 | UPDATE | 2012-09-30 |
+----------+------+--------+------------+
SELECT tt.*, result.* from tbl_trans tt
INNER JOIN
(SELECT DESCRIPTION, MAX(t.TRANS_ID) as TRANS_ID ,i.`CODE`,
GROUP_CONCAT(t.`TYPE`) TYPES
from tbl_invty i
LEFT JOIN tbl_trans t
ON i.CODE = t.CODE
GROUP BY i.`CODE`
HAVING NOT FIND_IN_SET('IDLE',TYPES)) result
ON tt.TRANS_ID = result.TRANS_ID;
SAMPLE FIDDLE
Try something like this:
SELECT i.des, i.code, max(t.trans_id), max(t.date)
FROM tbl_invty i left join tbl_trans t
ON t.code = i.code
WHERE i.code <> 1 AND t.type <> 'IDLE'
GROUP BY i.code;
SQL Fiddle..
EDIT: I just notice what you're looking for, check this:
SELECT i.des, i.code, max(t.trans_id), max(t.date)
FROM tbl_invty i left join tbl_trans t
ON t.code = i.code
where t.code not in (select code from tbl_trans
where type = 'IDLE')
group by i.code;
SQL Fiddle..
Related
I have a working query using INNER JOIN and a subquery but was wondering if there is a more effient way of writing it.
with prl
as
(
SELECT `number`, creator, notes
FROM ratings
INNER JOIN
projects on ratings.project_id = projects.project_id
WHERE ratings.rating = 5 AND projects.active = 1
)
SELECT prl.`number`, creator, notes
FROM prl
INNER JOIN(
SELECT `number`
HAVING COUNT(creator) > 1
)temp ON prl.`number` = temp.`number`
ORDER BY temp.`number`
projects table
project_id| number | creator | active |
| 1 | 3 | bob | 1 |
| 2 | 4 | mary | 1 |
| 3 | 5 | asi | 1 |
rating table
project_id| notes | rating |
| 1 | note1 | 5 |
| 1 | note2 | 5 |
| 3 | note3 | 5 |
| 1 | note4 | 1 |
| 2 | note5 | 5 |
| 3 | note6 | 2 |
result
| number | creator | notes |
| 3 | bob | note1 |
| 3 | bob | note2 |
It seems like you're using MySQL version that support window function. If so, then try this:
SELECT number, creator, notes
FROM
(SELECT p.number, p.creator, r.notes,
COUNT(creator) OVER (PARTITION BY creator) AS cnt
FROM project p
JOIN rating r ON p.project_id=r.project_id
WHERE r.rating=5
AND p.active = 1) v
WHERE cnt=2;
As far as whether this is more efficient, I'm not really sure because it depends in your table indexes but for a small dataset, I assume this will do well.
Demo fiddle
How to select all addons which a specific user has not buyed or are no longer valid?
Assuming currentdate is 2017-03-02 17:00:00
Table1 (users):
+-----------+----------+
| id | username |
+-----------+----------+
| 1 | Walter |
| 2 | Hank |
| 3 | John |
+-----------+----------+
Table2 (buyLog):
+-----------+----------+------------+---------------------+
| id | idUsers | idItems | validUntil |
+-----------+----------+------------+---------------------+
| 1 | 1 | 1 | 2016-03-02 14:15:47 |
| 2 | 1 | 1 | 2018-03-02 14:15:47 |
| 3 | 1 | 2 | 2016-03-02 14:15:47 |
| 4 | 2 | 1 | 2018-03-02 14:15:47 |
+-----------+----------+------------+---------------------+
Table3 (addons):
+-----------+----------+
| id | name |
+-----------+----------+
| 1 | Foo |
| 2 | Bar |
| 3 | Lorem |
+-----------+----------+
Expected output for user with id 1 should be:
+-----------+----------+
| id | name |
+-----------+----------+
| 2 | Bar |
| 3 | Lorem |
+-----------+----------+
See SQL Fiddle here: http://sqlfiddle.com/#!9/16356
Where I have the most problems is to handle the validUntil in the leftJoin.
I think I have to group by during the left join to tread only the most recent validUntil record. Maybe using max(validUntil)?
This code will work
http://sqlfiddle.com/#!9/16356/1/0
SELECT
C.ID AS 'ID',
C.NAME AS 'NAME'
FROM
(SELECT
A.id AS 'ID',A.name AS 'NAME',
CASE
WHEN B.YY > '2017-03-02 17:00:00' THEN 0
ELSE 1 END AS 'Tag'
FROM
addons AS A
LEFT JOIN
(SELECT idItems AS 'XX', MAX(validUntil) AS 'YY'
FROM
buyLog
WHERE idUsers = 1 GROUP BY 1) AS B
ON
A.id = B.XX) AS C
WHERE
C.Tag = 1
My sense is that neither your explanation nor your data set and desired result are adequate to the task of explaining the problem. The following query produces the desired result, but perhaps that's just coincidence...
SELECT a.*
FROM addons a
LEFT
JOIN buylog b
ON b.iditems = a.id
AND b.validuntil > NOW()
LEFT
JOIN users u
ON u.id = b.idusers
AND u.id = 1
WHERE b.validuntil IS NULL
AND u.id IS NULL;
I have two tables:
Problems
id | name
Responses
id | problem_id | user_id | value
I have the following statement.
SELECT
`problems`.name,
problem_id,
sum(value) as knowledge,
COUNT(*) as attempts FROM `responses`
LEFT JOIN `problems` ON `problems`.id = `responses`.problem_id
WHERE problem_id IS NOT NULL AND user_id = 4
GROUP BY problem_id
It produces a list like so:
| name | problem_id | knowledge | attempts |
| NULL | 1 | 6 | 6 |
| NULL | 2 | 5 | 6 |
| NULL | 3 | 4 | 6 |
| NULL | 4 | 3 | 5 |
I'm missing something and I would be grateful if someone could help format to:
| name | problem_id | knowledge | attempts |
| Problem A | 1 | 6 | 6 |
| Problem B | 2 | 5 | 6 |
| Problem C | 3 | 4 | 6 |
| Problem D | 4 | 3 | 5 |
Try this.
select p.`name`, p.`id`, r.`user_id`, sum(r.`value`) as knowledge
from
`responses` r
join `problems` p on r.`problem_id` = p.`id`
where
r.`user_id` = 4
group by p.`name`, p.`id`
You cannot have in your SELECT something that is neither an aggregate function (like SUM or AVG), nor a variable part of the GROUP BY.
In your case, the name is neither.
Some DBMS might let you do it (MySQL), but the result is unpredictable.
Solution:
SELECT
`problems`.name,
problem_id,
sum(value) as knowledge,
COUNT(*) as attempts FROM `responses`
LEFT JOIN `problems` ON `problems`.id = `responses`.problem_id
WHERE problem_id IS NOT NULL AND user_id = 4
GROUP BY problem_id, problems.name
I need to get emtpy fields where data is repeated
For example an customer can have two or more contact persons, so query return (just shorted qyery resul):
CUSTOMER_NAME| CONTACT_PERSON|ETC..
dell | Ighor |etc..
dell | Dima |etc..
but I'm need :
CUSTOMER_NAME| CONTACT_PERSON|etc...
dell | Ighor |etc..
NULL | Dima |etc..
SELECT
`contact`.*,
`branch_has_equipment`.*,
`branch_has_contact`.*,
`equipment`.*,
`customer_has_branch`.*,
`branch`.*,
`customer`.*,
`ip`.*
FROM `customer`
INNER JOIN `customer_has_branch`
ON `customer`.`customer_id` = `customer_has_branch`.`customer_id`
INNER JOIN `branch`
ON `customer_has_branch`.`branch_id` = `branch`.`branch_id`
INNER JOIN `branch_has_equipment`
ON `branch`.`branch_id` = `branch_has_equipment`.`branch_id`
INNER JOIN `equipment`
ON `branch_has_equipment`.`equipment_id` = `equipment`.`equipment_id`
INNER JOIN `branch_has_contact`
ON `branch`.`branch_id` = `branch_has_contact`.`branch_id`
INNER JOIN `contact`
ON `branch_has_contact`.`contact_id` = `contact`.`contact_id`
INNER JOIN `equipment_has_ip`
ON `equipment`.`equipment_id` = `equipment_has_ip`.`equipment_id`
INNER JOIN `ip`
ON `equipment_has_ip`.`equipment_id` = `ip`.`ip_id`
WHERE `customer`.`inservice` = 'Yes'
ORDER BY `customer`.`customer_name`
in additional, tables ^
Customer
customer_id
customer_name
inservice
service_type
comment
Branch
branch_id
city
address
Equipment
equipment_id
brand
model
connection_param
connection_type
serial_number
id
release
Contact
contact_id
name
surname
phone_mobile
phone_work
phone_other
position
customer_has_branch_id
customer_id
branch_id
Since I have no idea how any of those tables relate to one another, my only answer to you is to use an OUTER JOIN, which will keep NULL results.
I'm not seriously advocating this solution because really i think this sort of thing should be handled in application level code (e.g. a bit of PHP), but anyway, consider the following:
SELECT * FROM my_table;
+------+--------+--------+
| game | points | player |
+------+--------+--------+
| 1 | 5 | Adam |
| 1 | 8 | Alan |
| 1 | 7 | Brian |
| 1 | 6 | John |
| 2 | 2 | Adam |
| 2 | 3 | Alan |
| 2 | 4 | Brian |
| 2 | 6 | John |
+------+--------+--------+
SELECT IF(game= #prev,'',game)
, #prev := game
FROM my_table ORDER BY game,player;
+-------------------------+---------------+
| IF(game= #prev,'',game) | #prev := game |
+-------------------------+---------------+
| 1 | 1 |
| | 1 |
| | 1 |
| | 1 |
| 2 | 2 |
| | 2 |
| | 2 |
| | 2 |
+-------------------------+---------------+
I have a table something like this:
----------------------------------------
|uID|responseDate|field_01|field_02|etc|
+---+------------+--------+--------+---+
| 1 | 2011-12-02 | yes | no | |
| 2 | 2011-11-25 | no | yes | |
| 1 | 2012-01-02 | no | yes | |
| 2 | 2012-12-01 | no | no | |
| 3 | 2010-01-02 | yes | no | |
+---+------------+--------+--------+---+
I would like to get uIDs and responseDates for whom the latest response to field_01 is 'yes' - so my query should return:
------------------
|uID|responseDate|
+---+------------+
| 3 | 2010-01-02 |
+---+------------+
I'm using an inner join, but incorrectly. Here is my query:
SELECT f.uID, f.responseDate
FROM form_05 as f
INNER JOIN (
SELECT uID, max(responseDate) AS latest_date
FROM form_05
WHERE field_01 = 'yes'
GROUP BY uID ) dmax
ON dmax.uID = f.uID and dmax.latest_date = f.responseDate
ORDER BY f.uID ASC;
What this returns, however, is the latest entries for each uID where field_01 is yes, i.e.:
------------------
|uID|responseDate|
+---+------------+
| 1 | 2011-12-02 |
| 3 | 2010-01-02 |
+---+------------+
But I don't want that. I'd like to make it so that only the latest entry for each uID is eligible for the test. How can I restructure the query? Any pointers are greatly appreciated.
Give this a try and let me know if it doesn't work:
select t2.uid, t2.responseDate from t2
left join (
select t1.uid, max(t1.responseDate) as MaxDate from t1
group by t1.uid
) as SubQuery on t2.uid = SubQuery.uid and t2.responseDate = SubQuery.MaxDate
where MaxDate is not null and field_01 = "yes"