Simple SQL Maximum column query - mysql

I have two columns A and B. I want to select the value of column A where B has its maximum value.
SELECT MAX(B) FROM table_name
just gives me the value of B.
I can do another query with the value of B to get A, but is there a shorter way with just one SQL query?

select A
from MyTable
where B = (SELECT MAX(B) FROM MyTable)
or
select t.A
from MyTable t
inner join (
SELECT MAX(B) as BMAX FROM MyTable
) tm on t.B = t.BMAX

SELECT A
FROM table_name
WHERE B = (SELECT MAX(B) FROM table_name)

Related

Subquery to get derived value

I have the below table T in MySQL, with columns A and B.
I want to query this table to get a value 'C', that has the count of the number of times the value in Column 'A' appears in Column 'B'. For example, 1 appears 2 times in Column B, so the first row of column C should be 2. I don't want to iterate over the table, so I want to get this using subqueries. The desired output is given below.
I tried using the below query
SELECT A, B, (SELECT COUNT(A) FROM T WHERE B = A) AS C
FROM T
But I got 0 for all rows in column C. Please help me identify the mistake.
Use a correlated subquery:
SELECT t1.A, t1.B,
(SELECT COUNT(*) FROM tablename t2 WHERE t2.B = t1.A) AS C
FROM tablename t1
Or:
SELECT t1.A, t1.B,
(SELECT SUM(t2.B = t1.A) FROM tablename t2) AS C
FROM tablename t1
Or with a self LEFT join and aggregation:
SELECT t1.A, t1.B, COUNT(t2.B) AS c
FROM tablename t1 LEFT JOIN tablename t2
ON t2.B = t1.A
GROUP BY t1.A, t1.B

add select query result from tableA as a new column in tableB

I am creating a new table from joining two tables through below query:
select a.name, a.number, b.id, b.sub_num
from tableA a left join
tableB b
on a.number = concat(id,'-',Cast(sub_num as varchar);
Here, I want to add a new column into the new table which is select query result on tableA.
The table data would be something like below:
enter image description here
I am trying to use below query which is not correct as it is giving me multiple rows. I need sum of dext_number for condition dext_id = 17501 and group by of name and number columns.
select a.name, a.number, b.id, b.sub_num,
(select sum(dext_number) from tableA where dext_id = 17501 group by name, number) as newcol
from tableA a left join tableB b
on a.number = concat(id,'-',Cast(sub_num as varchar);
What is the best way to add this column here?
use following query
select a.name, a.number, b.id, b.sub_num, (select sum(dext_number) over(partition by name, number) from tableA
where dext_id = 'xyz' limit 1) as newcol
from tableA a
left join tableB b on a.number = concat(id,'-',Cast(sub_num as varchar);
If you want the exact output of the query image, use the following query
select L.name,L.number,L.dext_id,L.dext_number,
case when L.num > 1 then newcol
else NULL
end as newcol
from
(select *,
count(dext_number) over(partition by name, number) as num,
sum(dext_number) over(partition by name, number) as newcol
from tableA) L left join tableA R on L.dext_id = R.dext_id and L.name= R.name and L.number = R.number and L.dext_number = R.dext_number
And the combination of the first query with tableB will be as follows
select a.name, a.number, b.id, b.sub_num, (select
case when L.num > 1 then newcol
else NULL
end as newcol
from
(select *,
count(dext_number) over(partition by name, number) as num,
sum(dext_number) over(partition by name, number) as newcol
from Test) L left join Test R on L.dext_id = R.dext_id and L.name= R.name and L.number = R.number and L.dext_number = R.dext_number limit 1) as newcol
from tableA a
left join tableB b on a.number = concat(id,'-',Cast(sub_num as varchar);

Mysql re-using sums of subqueries

I have the following simplified query:
Select
(select sum(f1) from tableA a where a.id = t.id) sum1,
(select sum(f2) from tableB b where b.id = t.id) sum2,
t.*
from Table t;
My wish is to have sum1 and sum2 re-used without calculating them again:
Select
(select sum(f1) from tableA a where a.id = t.id) sum1,
(select sum(f2) from tableB b where b.id = t.id) sum2,
sum1 + sum2 `sum3`,
t.*
from Table t;
Of course i can do the following query but this will unnecessary double the run time:
Select
(select sum(f1) from tableA a where a.id = t.id) sum1,
(select sum(f2) from tableB b where b.id = t.id) sum2,
(select sum(f1) from tableA a where a.id = t.id) +
(select sum(f2) from tableB b where b.id = t.id) `sum3`,
t.*
from Table t;
or even inserting the sum1 and sum2 results to a temporary table but can't imaging i'm overlooking something to have mysql do some efficient querying on summed fields.
Is there a better, more efficient way to re-use summed fields?
Try running this query,
select Resutl.*,Result.sum1+Result.sum2 as sum3 from(
SELECT (SELECT SUM(f1) FROM tableA a WHERE a.id = t.id) sum1,
(SELECT SUM(f2) FROM tableB b WHERE b.id = t.id) sum2,
t.*
FROM Table t)Result
)
Hope it will help.
My wish is to have sum1 and sum2 re-used without calculating them again
Whoa, steady on. The original query is not as efficient as it might be. Without knowing what the data distribution looks like its hard to advise what the most appropriate query is, but assuming that the tuples in A and B have a foreign key constraint (implicit or explicit) on table T but no implicit foreign key restraint on each other, that t.id is unique, and most of the rows in tableT have corresponding rows in tableA and tableB then....
SELECT t.*, sum_f1, sum_f2
FROM tableT t
LEFT JOIN (SELECT a.id, SUM(f1) AS sum_f1
FROM tableA a
GROUP BY a.id) AS a_agg
ON t.id=a_agg.id
LEFT JOIN (SELECT b.id, SUM(f2) AS sum_f2
FROM tableB b
GROUP BY b.id) as b_agg
ON t.id=b_agg.id
GROUP BY t.id
Will be much more efficient.
(this also assumes that ONLY_FULL_GROUP_BY is disabled - otherwise you'll need to replace 't.*' in the SELECT clause and 't.id' in the group by clause with each of the attributes you need from the table).
Note that in practice you're rarely going to be looking at allyour data in a single query. Since MySQL doesn't handle push predicates very well, simply adding a filter in the outer SELECT probably won't be the optimal solution.
Once you've structured your query as above, it's trivial to add the sums:
SELECT t.*, sum_f1, sum_f2,
IFNULL(sum_f1,0)+INFULL(sum_f2,0) AS sum3
FROM tableT t
LEFT JOIN (SELECT a.id, SUM(f1) AS sum_f1
FROM tableA a
GROUP BY a.id) AS a_agg
ON t.id=a_agg.id
LEFT JOIN (SELECT b.id, SUM(f2) AS sum_f2
FROM tableB b
GROUP BY b.id) as b_agg
ON t.id=b_agg.id
GROUP BY t.id
(but note that I've made a lot of assumptions about your data and schema)

update 25 % of total rows returned by a select query

I have to insert data into a table with columns ( col 1, col2, col 3) .
I have a select query to select the data to be inserted in this table.
Select A.id, b.id , '1'
from table a
inner join table b on a.id=b.id
where a.col= 'somevalue'and b.col ='othervalue' ...
If you notice the third column in the select statment i have a hard coded value '1'. The current requirement is to set only the 25 % of the total rows with '1' and rest 75 % with '0'. Now the difficult part is we cant be sure how many rows the select statement will come up with.
We can also use an update statement to update the 25 % rows with 1 and rest keep it as '0' but the limit fucntion will not accept any user defined variable.
Can anyone suggest something on this ?
I am using MYSQL
When you insert the data into the table, keep a row number, and use modulo arithmetic:
insert into . . .
select a_id, b_id, (mod(rn, 4) = 0) as flag
from (Select A.id as a_id, b.id as b_id , (#rn := #rn + 1) as rn
from table a inner join
table b
on a.id = b.id cross join
(select #rn := 0) vars
where a.col = 'somevalue' and b.col = 'othervalue' ...
) i;
One nice feature of taking every fourth row is that this works well, even if the data is somehow ordered because of the join.
Use a subquery to get the total number of rows. Then use a user-defined variable to get the row number in the output, and compare it to 25% of the total.
SELECT a.id, b.id, IF(#counter < pct25, '1', '0'), #counter := #counter + 1
FROM table1 a
JOIN table2 b ON a.id = b.id
JOIN (SELECT COUNT(*)/25 AS pct25
FROM table1 a
JOIN table2 b ON a.id = b.id) AS x
CROSS JOIN (SELECT #counter := 0) AS var

MAX on two columns in mysql

I wonder if there is better way to get max from column c1 and then max from column c2 for selected rows than
SELECT MAX(c1) , MAX(c2) FROM t GROUP BY c1 HAVING c1 = MAX(c1)
SELECT Max(t2.c1) as C1,
Max(t1.c2) as C2
FROM t t1
INNER JOIN (SELECT Max(c1) AS C1
FROM t) t2
ON t1.c1 = t2.c1
I'm not quite sure whether you want all distinct c1's or just the maximum.
If you want all c1's:
SELECT c1, MAX(c2) FROM t GROUP BY c1;
If you want only the maximum c1:
SELECT c1, c2 FROM t ORDER BY c1 DESC, c2 DESC LIMIT 1;
Just read your comment on hkutluay's response, this might be what you want:
select MAX(colName)
from
(select col1 as colName
from tableName
union
select col2
from tableName) subqueryName
I know mysql does not have CTE's; but because the question is also marked SQL, and the CTE is a reasonable clean solution for the subquery, for completeness here is a CTE-version:
WITH zmax AS (
SELECT MAX(v1) AS v1
FROM ztable
)
SELECT zt.v1
, MAX(zt.v2) AS v2
FROM ztable zt
JOIN zmax mx ON zt.v1 = mx.v1
GROUP BY zt.v1
;