How mysql add count colnum to a table - mysql

I have tableA and want add count colnum to it , count is total rows of tableA and is same at all rows in result table ,tableA like below :
note: table A is result of other query
tableA
id | name | rank |
-------------------
1 | John | 12 |
2 | Maria | 18 |
3 | Steph | 44 |
4 | Jay | 17 |
and result should be :
id | name | rank | total | rank/total
---------------------------------------
1 | John | 12 | 4 | 3
2 | Maria | 18 | 4 | 4.5
3 | Steph | 44 | 4 | 11
4 | Jay | 17 | 4 | 4.25
how can do that with MYSQL

To get the total rows in your table, do this:
SELEcT count(*) FROM TableA
You can then combine this query in the SELEcT of another query and make a computation from it, which gives this :
SELEcT *, (SELEcT count(*) FROM TableA) AS total, rank / (SELEcT count(*) FROM TableA) AS 'rank/total'
FROM tableA
if tableA is the result of another query, do
SELEcT *, (SELEcT count(*) FROM TableA) AS total, rank / (SELEcT count(*) FROM TableA) AS 'rank/total'
FROM ( insert_the_other_query_here ) tableA

Check if using a variable helps you helps you:
SET #total = SELECT COUNT(1) FROM tableA;
SELECT name, rank, #total AS total, rank/#total AS 'rank/total' FROM tableA;

Related

MySQL Query with distinct on a column value

I have this table (with 100k+ rows):
room_id | emote_id | count | since
----------------------------------------
1 | 22 | 718| 1577135778
1 | 23 | 124| 1577135178
1 | 24 | 842| 1577135641
2 | 22 | 124| 1577135748
2 | 23 | 345| 1577136441
2 | 24 | 43| 1577543578
3 | 22 | 94| 1572135778
3 | 23 | 4718| 1577135641
3 | 24 | 18| 1577134661
4 | 22 | 78| 1577125641
4 | 23 | 128| 1577135778
4 | 24 | 278| 1577132577
I want to get for each emote_id the row where count is the highest for this emote_id
So for this example I'd like to get this as response:
room_id | emote_id | count | since
----------------------------------------
1 | 22 | 718| 1577135778
3 | 23 | 4718| 1577135641
1 | 24 | 842| 1577135641
I'm stuck at building the query and need help. :(
You can use nested subquery with max() aggregation
select t1.*
from tab t1
join (select emote_id, max(count) as count
from tab
group by emote_id ) t2
on t1.emote_id = t2.emote_id
and t1.count = t2.count
for db version 8+ you can use window analytic functions such as dense_rank():
select room_id, emote_id, count, since
from
(
select t.*, dense_rank() over (partition by emote_id order by count desc) as dr
from tab t
) tt
where tt.dr = 1
Demo
All matching maximum values for count return through use of dense_rank() in case of tie( having equal valued count for any of emote_id ). If analytic function was row_number(), then only one row would return even if tie occurs.

Select DISTINCT and MAX in the same query and list all value in rows attach

Im trying to combine distinct and max assign_id or last assign_id in table below but doesnt get a right value.
Table_task
ASSIGN_ID | DRV_ID | VEHICLE_ID
--------------------------------------
1 | EFFA | 1000
2 | SAM | 1001
3 | FIZA | 1004
4 | JIJO | 1000
5 | LISA | 1000
How to get value display as below ?
ASSIGN_ID | DRV_ID | VEHICLE_ID
-----------------------------------------
2 | SAM | 1001
3 | FIZA | 1004
5 | LISA | 1000
Assuming assign_id doesn't have a ties, then you can use subquery :
select t.*
from table t
where assign_id = (select max(t1.assign_id)
from table t1
where t1.vehicle_id = t.vehicle_id
);
Have a sub-query that returns each vehicle_id's max assign_id. JOIN with that result:
select t1.*
from task t1
join (select vehicle_id, max(assign_id) assign_id
from task
group by vehicle_id) t2
on t1.vehicle_id= t2.vehicle_id
and t1.assign_id = t2.assign_id

How to write a MySQL SELECT Query to achieve this result?

I have an abstract problem which can be simplified as the following problem: Assume that we have two tables persons and names that look as follows:
SELECT * FROM persons;
+----+-------+--------+
| id | name | fan_of |
+----+-------+--------+
| 1 | alice | 2 |
| 2 | bob | 4 |
| 3 | carol | 1 |
| 4 | dave | 3 |
| 5 | bob | 2 |
+----+-------+--------+
and
SELECT * FROM names;
+----+-------+--------+
| id | name | active |
+----+-------+--------+
| 1 | alice | 1 |
| 2 | bob | 1 |
| 3 | carol | 0 |
| 4 | dave | 1 |
+----+-------+--------+
Every person (a row in the persons) table is a fan of itself or another person (represented by that other persons id in the fan_of column). The names table contains names that can be active or inactive.
For a given offset k, I want to SELECT the persons (rows of persons) that have the k+1-th active name as their name or that have one of these people as their fans. For example, if the offset is 1, the second active name is bob and hence I want to select all people with the name bob plus the people that have one of these bobs as their fans, which is in this example the row of persons with id=4. This means that I want to have the result:
+----+------+--------+
| id | name | fan_of |
+----+------+--------+
| 2 | bob | 4 |
| 4 | dave | 3 |
| 5 | bob | 2 |
+----+------+--------+
What I have so far is the following query:
1 SELECT * FROM persons WHERE
2 EXISTS (
3 SELECT * FROM (
4 SELECT * FROM names WHERE active=true LIMIT 1 OFFSET 1
5 ) AS selectedname WHERE (selectedname.name=persons.name)
6 )
7 OR
8 EXISTS (
9 SELECT * FROM(
10 SELECT * FROM persons WHERE EXISTS (
11 SELECT * FROM (
12 SELECT * FROM names WHERE active=true LIMIT 1 OFFSET 1
13 ) AS selectedname WHERE (selectedname.name=persons.name)
14 )
15 ) AS personswiththatname WHERE persons.id=personswiththatname.fan_of
16 );
It gives me the desired result from above but please note that it is inefficient because the lines 3-5 and 11-13 are the same.
I have the following two questions:
What can be done to avoid this inefficiency?
I actually need to distinguish between those rows that came from the
name condition (here the rows with name=bob) and those that came
from the fan_of condition (here the row with name=dave). This
could be done in the application code but then I would need another
database query before to find out the k+1-th active name and this might
be slow (please correct me if this is the better solution). I would
rather prefer an additional column z that helps me to distinguish
like
+----+------+--------+---+
| id | name | fan_of | z |
+----+------+--------+---+
| 2 | bob | 4 | 1 |
| 4 | dave | 3 | 0 |
| 5 | bob | 2 | 1 |
+----+------+--------+---+
How can such an output be achieved?
It looks like I can get the minimum you want to achieve using parameters (should this be an option).
It's not pretty, but I can't see a simple way of achieving what you're asking for, so this is what I have so far....(set #offset to suit 'k')
SET #offset = 1;
SET #name = (SELECT name FROM (select name, #rank := #rank +1 as Rank from names n, (SELECT #rank := 0) r where active !=0) as activeRanked where activeRanked.rank = (1 + #offset));
select
a.*
From persons a
where (a.name = #name) OR (a.id IN (SELECT fan_of from persons where name = #name));
If you still don't have an answer by the time I've had food, I'll look at part 2.
(hopefully I've read your brief correctly)
P.S. I've kept the #name SQL in a single line as it seems to read better in this context.
Edit: Here's a pretty messy but functional indicator of source, using your example. Z = 1 is where the row is from the name, '0' is from fan_of
SET #offset = 1;
SET #name = (SELECT name FROM (select name, #rank := #rank +1 as Rank from names n, (SELECT #rank := 0) r where active !=0) as activeRanked where activeRanked.rank = (1 + #offset));
select
a.*,'1' as z
From persons a
where (a.name = #name)
union
select
a.*,'0' as z
From persons a
where (a.id IN (SELECT fan_of from persons where name = #name));
Distinct ID Query:
SET #offset = 1;
SET #name = (SELECT name FROM (select name, #rank := #rank +1 as Rank from names n, (SELECT #rank := 0) r where active !=0) as activeRanked where activeRanked.rank = (1 + #offset));
SELECT id, name, fan_of, z FROM
(select
distinct a.id,
a.name,
a.fan_of,
1 as z
From persons a
where (a.name = #name)
union
select
distinct a.id,
a.name,
a.fan_of,
0 as z
From persons a
where (a.id IN (SELECT fan_of from persons where name = #name))
ORDER BY z desc) qry
GROUP BY id;
This produces:
+----+------+--------+---+
| id | name | fan_of | z |
+----+------+--------+---+
| 2 | bob | 4 | 1 |
| 5 | bob | 2 | 1 |
| 4 | dave | 3 | 0 |
+----+------+--------+---+

SQL show difference of two tables and compare the result to another table with different database

This is my dbtest1 structure
Database name: dbtest1
Table tbl1
id | name | age
1 | johny | 26
2 | jane | 25
3 | mike | 32
4 | jean | 33
Table tbl2
id | name | age
1 | john | 26
2 | jane | 25
3 | mike | 42
using this query below to get the difference of the two table.
SELECT *
FROM (
SELECT *, 'tableT1' AS fromTable FROM tbl1
UNION ALL
SELECT *, 'tableT2' AS fromTable FROM tbl2
) tbl
GROUP BY id, name, age
HAVING count(*) = 1
ORDER BY id;
I get this result.
id | name | age | fromTable
1 | john | 26 | tableT1
3 | mike | 42 | tableT2
4 | jean | 33 | tableT1
Now my problem is how can I able to compare the above result to dbtest2?I have no idea how to implement this..thanks in advance.
Database name: dbtest2
Table tbl3
id | name | age
1 | john | 26
2 | jane | 25
3 | mike | 42
You can use fully qualified names. They are generally have the following syntax:
DATABASE_NAME.TABLE_NAME.COLUMN_NAME
Where each of the identifiers separated with . is the name of their namespaces. When you are issuing a query that is in current namespace, you can omit the name of the namespace, like you say desc tbl3 when you are in dbtest2.
Here is how you would do it in your query:
SELECT *
FROM (
SELECT *, 'tableT1' AS fromTable FROM tbl1
UNION ALL
SELECT *, 'tableT2' AS fromTable FROM tbl2
UNION ALL
SELECT *, 'tableT3' AS fromTable FROM dbtest2.tbl3 # Here use fully qualified table name
) tbl
GROUP BY id, name, age
HAVING count(*) = 1
ORDER BY id;

I need to get the average for every 3 records in one table and update column in separate table

Table Mytable1
Id | Actual
1 ! 10020
2 | 12203
3 | 12312
4 | 12453
5 | 13211
6 | 12838
7 | 10l29
Using the following syntax:
SELECT AVG(Actual), CEIL((#rank:=#rank+1)/3) AS rank FROM mytable1 Group BY rank;
Produces the following type of result:
| AVG(Actual) | rank |
+-------------+------+
| 12835.5455 | 1 |
| 12523.1818 | 2 |
| 12343.3636 | 3 |
I would like to take AVG(Actual) column and UPDATE a second existing table Mytable2
Id | Predict |
1 | 11133
2 | 12312
3 | 13221
I would like to get the following where the Actual value matches the ID as RANK
Id | Predict | Actual
1 | 11133 | 12835.5455
2 | 12312 | 12523.1818
3 | 13221 | 12343.3636
IMPORTANT REQUIREMENT
I need to set an offset much like the following syntax:
SELECT #rank := #rank + 1 AS Id , Mytable2.Actual FROM Mytable LIMIT 3 OFFSET 4);
PLEASE NOTE THE AVERAGE NUMBER ARE MADE UP IN EXAMPLES
you can join your existing query in the UPDATE statement
UPDATE Table2 T2
JOIN (
SELECT AVG(Actual) as AverageValue,
CEIL((#rank:=#rank+1)/3) AS rank
FROM Table1, (select #rank:=0) t
Group BY rank )T1
on T2.id = T1.rank
SET Actual = T1.AverageValue