MySQL Query suggestion with access id - mysql

I have a MySQL table like this
ownerlisting_access_id property_id mainaccess_id subaccess_id access_value
62 2 35 41 Yes
64 2 35 36 Yes
123 4 35 41 Yes
125 4 35 36 Yes
306 7 35 41 Yes
307 7 35 42 Yes
308 7 35 36 Yes
I want a query that will give me this output using subaccess_id(41,42,36) and mainaccess_id(35) -
ownerlisting_access_id property_id mainaccess_id subaccess_id access_value
306 7 35 41 Yes
307 7 35 42 Yes
308 7 35 36 Yes
I need to get the property_id as 7 using sub access id with 41, 42, 36

The fastest way to get an answer to your question is to describe the PROBLEM not just show results you need. It's not clear what is the logic behind your desired output. I guess you need the rows with the highest property_id for each group subaccess_id. If so here is the query:
select * from t
join (select subaccess_id, max(property_id) MAX_property_id
from t
where mainaccess_id=35
and
subaccess_id in (41,42,36)
group by subaccess_id
) t1
on t.subaccess_id=t1.subaccess_id
and
t.property_id=t1.MAX_property_id
SQLFiddle demo
Also here is a query that outputs results you needed :) But I guess it doesn't solve your PROBLEM:
select * from t where property_id=7

Try this:
SELECT table1.* FROM (
select property_id, group_concat(DISTINCT subaccess_id ORDER BY subaccess_id) as list
from table1 as t1 group by property_id
) a, table1
WHERE a.property_id = table1.property_id
AND a.list = '36,41,42'
Working query: http://sqlfiddle.com/#!2/4744ea/2

SELECT MAX(DISTINCT property_ID) AS property_ID, mainaccess_id,
MAX(DISTINCT subaccess_id) AS subaccess_id, MAX(DISTINCT access_value)
FROM tableName GROUP BY mainaccess_id ORDER BY mainaccess_id

SELECT property_ID, mainaccess_id, subaccess_id, access_value
FROM tableName t1
WHERE t1.mainaccess_id = 35
AND (t1.subaccess_id = 41 OR t1.subaccess_id = 42 OR t1.subaccess_id = 36)
AND t1.property_ID = (SELECT MAX(t2.property_ID)
FROM tableName t2
WHERE t2.mainaccess_id = 35
AND (t2.subaccess_id = 41 OR t2.subaccess_id = 42 OR t2.subaccess_id = 36))

Related

Select corresponding value from second table (Mysql)

Struggling with some sql, would appreciate some guidance.
Have two tables logs and sense
logs –
assetid ts nodeid status
1 2017-10-26 14:00:10 73 240
2 2017-10-26 14:00:06 21 160
3 2017-10-26 14:00:04 18 230
4 2017-10-26 14:00:02 19 400
5 2017-10-26 14:00:00 21 190
1 2017-10-26 13:20:08 18 20
2 2017-10-26 13:06:10 20 160
3 2017-10-26 13:03:04 17 230
sense –
status value
20 5
160 37
190 39
230 56
240 58
400 90
Trying to find the correct syntax to only show the latest record (in datetime) of each assetid and then show the corresponding value from the sense table (based on the matching status in both tables) to produce –
assetid ts nodeid status value
1 2017-10-26 14:00:10 73 240 58
2 2017-10-26 14:00:06 21 160 37
3 2017-10-26 14:00:04 18 230 56
4 2017-10-26 14:00:02 19 400 90
5 2017-10-26 14:00:00 21 190 39
Have tried –
Select assetid, ts, nodeid, status, value
From
logs
Join sense X on X.status = logs.status
Group by assetid
Order by ts DESC
But this only outputs 1 row (instead of 5)
assetid ts nodeid status value
1 2017-10-26 14:00:10 73 240 58
Removing
Join sense X on X.status = logs.status
of course outputs all records but that is not required.
Thoughts appreciated.
Regards
Active
Actually your query is returning 5 rows, 1 for each id. But it won't return rows with latest ts for each id. You can verify this by clicking on the link for demo. You can compare results of both queries.
To achieve this task,following query will help you:
Select l.assetid, l.ts, logs.nodeid, X.status, X.value
From
logs
inner Join sense X on X.status = logs.status
inner join (select assetid, max(ts) as ts from logs group by assetid) l
on l.assetid = logs.assetid and logs.ts = l.ts
Group by l.assetid
Order by l.ts DESC;
Click here for Demo
EDIT:
If dataype of ts is string then replace max(ts) in above query with:
max(str_to_date(ts,'%d%m%y'))
Feel free to ask any doubts.
Hope it helps!
Try this
Select a1.assetid, MAX(a1.ts), a1.nodeid, a1.status, X.value
From
logs a1
inner join sense X on X.status = a1.status
Group by assetid, a1.nodeid, a1.status, X.value
Order by ts DESC
Use GROUP BY to find minimum for each assetid and then JOIN with the logs and sense
Select *
FROM logs l
JOIN sense s ON s.status = l.status
JOIN
(
Select assetid, max(ts) maxts
From logs
Group by assetid
) t ON t.assetid = l.assetid and l.ts = t.maxts
demo
On MY SQL 8.0.2
WITH CTE as
(
Select A.assetid, A.ts, A.nodeid, A.status, B.value, row_number() over(PARTITION BY A.assetid ORDER BY A.ts DESC) AS rn
from logs as A
inner join sense B ON A.status=B.status
)
SELECT *
FROM CTE
WHERE rn='1';

MySQL last 50 records

I have to get the last 50 records from my MySQL database.
Here is the structure of my test database:
ID S1 S2 S3 Date-time Label
13 32 55 33 2017-09-05 13:15:06 temperature
16 111 222 66 2017-09-05 19:22:14 temperature
17 44 55 33 2017-09-05 19:22:14 temperature
18 55 11 88 2017-09-12 14:22:00 temperature
21 77 1 200 2017-09-15 12:24:06 temperature
22 22 55 11 2017-09-19 14:37:00 temperature
How could I show only the last 3 data? for example:
18 55 11 88 2017-09-12 14:22:00 temperature
21 77 1 200 2017-09-15 12:24:06 temperature
22 22 55 11 2017-09-19 14:37:00 temperature
Greetings and thank you.
In Oracle12c you can use the fetch keywork:
SELECT *
FROM table
ORDER BY id DESC
FETCH FIRST 50 ROWS ONLY;
FOR ORACLE:
SELECT * FROM (
SELECT ID,
S1,
S2,
S3,
Date-time,
Label
FROM TABLE
ORDER BY ID DESC)
WHERE ROWNUM <= 50;
FOR MYSQL:
SELECT ID,
S1,
S2,
S3,
Date-time,
Label
FROM TABLE
ORDER BY ID DESC
LIMIT 50;
Here is a quick doc:
https://www.w3schools.com/sql/sql_top.asp
Edit:
For the last 50 rows:
SELECT * FROM (
SELECT * FROM table ORDER BY id DESC LIMIT 50
) sub
ORDER BY id ASC
Use Top N Query (row num<=50) fro first, for last 50 you can use "order by id desc"
First I was confused with the Post between ORACLE and MYSQL I apologize.
The solution at the end was the following:
SELECT * FROM inv ORDER BY id DESC LIMIT 50
then transform the ARRAY that I collect with the function:
var dorde = d0.reverse ();
thanks for everything.

MySQL calculate difference in count column between two queries

I have two different queries. One for "plus" and one for "minus". I want to find the difference in the count value for each player.
I tried union all and got some very weird numbers.
Here are the results of each query which I ned to find the difference of:
fk_plus_player1_id cnt
90 71
65 68
79 66
45 59
64 57
27 56
55 56
93 55
37 55
40 44
1 36
84 33
20 31
24 28
8 23
fk_minus_player1_id cnt
93 44
64 42
79 40
37 35
90 33
20 31
84 31
27 30
65 30
40 26
1 26
24 25
45 25
55 22
8 10
How would I accomplish this? Thanks in advance for your help. I am a noob...
UGH...Trying to do the join method. Having issues, getting no results, just 4 empty columns. This is what I am trying
SELECT
*
FROM
(
SELECT
statement for plus results here
) AS tp
JOIN (
SELECT
statement for minus results here
) AS tm ON tp.fk_plus_player1_id = tm.fk_minus_player1_id
GROUP BY
fk_plus_player1_id
suggestions??
You have two tables.
You want for each player, the difference of the counts.
So :
SELECT t1.fk_minus_player1_id AS player, ABS(t1.cnt - t2.cnt) AS difference
FROM table1 t1, table2 t2
WHERE t1.fk_minus_player1_id = t2.fk_plus_player1_id
GROUP BY t1.fk_minus_player1_id;
Maybe this is what you're looking for ?
WITH query1 AS
(SELECT t1.fk_minus_player1_id AS player, (t1.cnt - IFNULL(t2.cnt,0)) AS difference
FROM table1 t1 LEFT OUTER JOIN table2 t2 ON t1.fk_minus_player1_id = t2.fk_plus_player1_id
GROUP BY t1.fk_minus_player1_id),
query2 AS (SELECT t2.fk_plus_player1_id AS player, (IFNULL(t1.cnt,0) - t2.cnt) AS difference
FROM table2 t2 LEFT OUTER JOIN table1 t1 ON t1.fk_minus_player1_id = t2.fk_plus_player1_id
GROUP BY t2.fk_plus_player1_id)
(SELECT player, difference
FROM query1)
UNION
(SELECT player, difference
FROM query2 WHERE player NOT IN (SELECT player FROM query1))
You run the risk that the same players are not in both lists. The solution is union all with group by:
select player1id, sum(pluscnt) as pluscnt, sum(minuscnt) as minuscnt,
(sum(pluscnt) - sum(minuscnt)) as diff
from ((select player1id, cnt as pluscnt, 0 as minuscnt
from plustable
) union all
(select player1id, 0, cnt
from minustable
)
) t
group by player1id;

How to properly exclude rows with references to each other?

This question is based on the not very trivial question How to remove two duplicate column. I already suggested solution on that question, but I think there is some more suitable and elegant solution than mine.
There is some table of private messages with columns msg_id, from, to.
And we have this data in it:
msg_id from to
----------------
1 46 0
2 46 18
3 46 50
4 46 39
5 46 11
6 11 46
7 46 12
8 46 56
9 46 11
We need to exclude rows with the conversations, in which there are more than one message (like rows with msg_id = 5, 6 and 9) and in the same time we need to leave first row in output among these rows. In general output should be like this (note: without msg_id = 6 and msg_id = 9):
msg_id from to
----------------
1 46 0
2 46 18
3 46 50
4 46 39
5 46 11
7 46 12
8 46 56
My solution is:
select distinct pm.`from`, pm.`to`
from `tsk_private_message` pm
left join
(select distinct pm.`from`, pm.`to`
from `tsk_private_message` pm
inner join `tsk_private_message` pm2
on (pm.`to` = pm2.`from`) and (pm2.`to` <> pm.`from`)) a
using (`from`, `to`)
where a.`from` is null;
I just search unnecessary rows among these conversations via subquery and "subtract" result from the main table. What do you think? Is there more elegant and more simple solution? I just really don't like this tricky code.
Here is SQL Fiddle
SELECT mx.msg_id, pm.ffrom, pm.tto
FROM tsk_private_message pm
WHERE NOT EXISTS (
SELECT * FROM tsk_private_message nx1
WHERE nx1.ffrom = pm.ffrom AND nx1.tto = pm.tto
AND nx1.msg_id < pm.msg_id
)
AND NOT EXISTS (
SELECT * FROM tsk_private_message nx2
WHERE nx2.ffrom = pm.tto AND nx2.tto = pm.ffrom
AND nx2.msg_id < pm.msg_id
);
Note: I renamed the to and from columns to tto and ffrom, because to and from both are keywords in SQL and I don't like quoting identifiers.
Extra: sqlfiddle (courtesy of Alexander Myshov)
SELECT *
FROM
tsk_private_message INNER JOIN (
SELECT MIN(id) min_id
FROM tsk_private_message
GROUP BY
LEAST(`from`, `to`),
GREATEST(`from`, `to`)) min_msg
ON tsk_private_message.id = min_msg.min_id
ORDER BY
id
Please see fiddle here.

MySQL single table, select value based on multiple rows

From the table below, how would I select all animalIds that have a specific combination of attributeIds e.g. if I supplied attributeIds 455 & 685 I'd expect to get back animalIds 55 & 93
Table name: animalAttributes
id attributeId animalId
1 455 55
2 233 55
3 685 55
4 999 89
5 455 89
6 333 93
7 685 93
8 455 93
I have the following query that seems to work, however, I'm not sure if there is a more robust way?
SELECT animalId
FROM animalAttributes
WHERE attributeId IN (455,685)
GROUP BY animalId
HAVING COUNT(DISTINCT attributeId) = 2;
If you really want accurate results, you could go with a fool-proof method like this:
select distinct base.animalId
from animalAttributes base
join animalAttributes a on base.animalId = a.animalId
and a.attributeId = 455
where base.attributeId = 685
If you later needed 3 matching attributes, you could just add another join:
select distinct base.animalId
from animalAttributes base
join animalAttributes a on base.animalId = a.animalId
and a.attributeId = 455
join animalAttributes b on base.animalId = b.animalId
and b.attributeId = 999
where base.attributeId = 685
SELECT DISTINCT `animalId` FROM `animalAttributes` WHERE `attributeId` = 455
INTERSECT
SELECT DISTINCT `animalId` FROM `animalAttributes` WHERE `attributeId` = 685
SELECT DISTINCT animalId
FROM animalAttributes
WHERE attributeId IN (455,685)
or
SELECT animalId
FROM animalAttributes
WHERE attributeId IN (455,685)
GROUP BY animalId