Select least 6 values across 100 columns in a MySQL row - mysql

I have a table with 103 columns. First column (rowID) is the row index, the next one contains a date, and the third one contains a string (a name), then there are 100 columns (named A1 to A100) that each contain an integer. I am trying to write a query to fetch the lowest 6 values among those 100 columns, for each row.
Here is what I tried. I had to write out all 100 columns (is there a better way?), and this only gets me the smallest 1, and NOT the smallest 6:
SELECT LEAST(A1,A2,A3,A4,...A100) FROM myTable WHERE rowID=1
I am thinking maybe I can use 5 queries to run the least command each time, returning the result to the backend which will then exclude the column that contained the least value in the previous query. However I am not sure this is the best way because I am trying to keep it all within MySQL. Is there a way to use sub-queries to do this? Or another effective method. Any help would be appreciated!
Edit: I also need to know the columns from which those minimum 6 values were obtained.

You seem to be storing a multi-valued attribute in a denormalized way.
If you need to do set-oriented comparisons on these values, they should be stored in rows, not columns.
You can "unpivot" them, so each value is on its own row, like this:
SELECT 1 AS ValNo, A1 AS Val FROM MyTable WHERE rowID=1
UNION ALL
SELECT 2, A2 FROM MyTable WHERE rowID=1
UNION ALL
SELECT 3, A3 FROM MyTable WHERE rowID=1
UNION ALL
SELECT 4, A4 FROM MyTable WHERE rowID=1
UNION ALL
...
UNION ALL
SELECT 100, A100 FROM MyTable WHERE rowID=1
Then by putting that into a subquery, get the lowest 6 values.
SELECT ValNo, Val
FROM ( ... subquery above ... ) AS t
ORDER BY Val
LIMIT 6
You would be better off to store a table with one column for the value, and up to 100 rows for each rowId:
CREATE TABLE MyNewTable (
RowId INT,
OrdinalId TINYINT, -- 1 to 100
Aval INT,
PRIMARY KEY (RowId, OrdinalId)
);
Then you can query it more simply:
SELECT OrdinalId, Aval
FROM MyNewTable
WHERE RowId = 1
ORDER BY Aval
LIMIT 6;

Related

Query to Check for Values Not Matching List in Where Clause

I am writing a SQL query that uses the IN operator in the WHERE clause on a table that contains millions of records.
I would like to know for the specific values I am checking in my WHERE clause, which ones are missing from the table.
How do I write a query to check for the values that do not result in a match according to the values in my WHERE clause for those values specifically?
For example -
SELECT *
FROM employees
WHERE emp_id IN (123, 456, 789)
Let's say that this query returns 2 rows for emp_id = 123 and emp_id = 456.
I want to write a query that shows me what was missing, illustrating that there was no row in the table specifically for emp_id = 789.
To find rows missing, you must have a canonical set of rows to compare with. Here's an example using the VALUES statement (which is new in MySQL 8.0).
Suppose we have a list 1, 2, 19, 64 and we want to find which ones don't have matching rows in the table mytable.
SELECT t.column_0
FROM (VALUES ROW(1), ROW(2), ROW(19), ROW(64)) AS t
LEFT OUTER JOIN mytable ON t.column_0 = mytable.id
WHERE mytable.id IS NULL;
If you use a version older than MySQL 8.0, you can replace the derived table with this more verbose syntax:
...
FROM (SELECT 1 AS column_0 UNION SELECT 2 UNION SELECT 19 UNION SELECT 64) AS t
...
Or you could also create a temporary table and fill it with the values you want to search for, one value per row.
You can use the opposite of IN which is NOT IN(). Keep the bit inside the brackets the same and you'll get every record that doesn't have that

Adding a column to a union select statement results with more result rows

I made a database for stock management system.
For some reporting i need union of two queries from two different tables,
after writing a select statement I noticed that results are lacking one row.
After adding one more column the missing row appeared.
I am providing print screens of queries and results.
Please use Union All instead of Union. As you are using Union here it will will eliminate duplicate rows from your output.
This isn't surprising.
UNION removes duplicate rows. So, when you add a new column you make rows that were the same different. For instance:
Table1
x y
1 'a'
1 'b'
Table2
x y
1 'c'
2 'd'
The following query:
select x from table1
union
select x from table2
returns:
1
2
However, including y:
select x, y from table1
union
select x, y from table2
You get four rows:
x y
1 'a'
1 'b'
1 'c'
2 'd'
If you used union all, you would get the same number of rows in both cases. In the first case, you would see duplicate rows in the result set.
This answers the question that you asked. If you want a particular result set, ask a new question is sample data, desired results, and your queries as text in the question.

Mysql union does not sum same values

Below is my sample code for mysql
SELECT ROUND(SUM(final.spend),4) as tot_spend
FROM
(SELECT 1 as spend FROM `tab1` as tds WHERE 1
UNION
SELECT 1 as spend FROM `tab2` as obm WHERE 1
) as final
For better understanding I replace the column value as 1 in query, because value from both tables are same,If run above query I get result 1, it does not sum the value, if I change any one table value for Eg. change tab2 value as 2 and run means it shows 3, for my understanding if the value from both tables are same means SUM wont work , differ means its SUM the value from the tables, is the default one or my understanding is wrong? Anyone help to solve my issue, I need to sum any value(same or differ) from both table.
The UNION operator selects only distinct values by default. To allow duplicate values, use UNION ALL:
SELECT ROUND(SUM(final.spend),4) as tot_spend
FROM
(SELECT 1 as spend FROM `tab1` as tds WHERE 1
UNION ALL
SELECT 1 as spend FROM `tab2` as obm WHERE 1
) as final
This will give you the correct sum.

Comparing two large data sets or tables in mysql

Lets say I have 2 large csv files (more than 1 million rows) and both are a list of names with rank. The goal is to find the same names among both lists, unique names to list 1, and unique names to list 2.
I wanted to do this is mySQL so I created a table for each list but looping through over a million records a million times seems like a poor way of doing this and very slow. How would you do this?
This is an example but bad query: http://sqlfiddle.com/#!2/9f272/2
The following returns the number of times that names appear in each table, with the count. If names are unique in each table, then it might return something like:
InTable1 InTable2 Count
1 0 xxx
0 1 yyy
1 1 zzz
The query uses a union all and group by:
select InTable1, InTable2, count(*), min(name), max(name)
from (select name, sum(which = 1) as InTable1, sum(which = 2) as InTable2
from ((select name, 1 as which
from table1
) union all
(select name, 2 as which
from table2
)
) t
group by name
) t
group by InTable1, InTable2;
EDIT:
You need to create indexes. Here is the syntax:
create index table1_name on table1(name);
create index table2_name on table2(name);

Comparing field value with count of occurrences

i dont exactly know how write down this query,
so im asking your guys and gals help.
so, i have a table the contains something like:
COLUMNS
id,keyword,pages
what i basicly need is to get all the rows where pages!=count(keyword)
this is basicly how i tried to do it anyway.
so it should be really simple, return all rows, where the keyword count does not equal the pages column value.
so, if for example the data is like this :
ROW A: 1, aaa, 3
ROW B: 4, aaa, 3
ROW C: 5, aaa, 3
ROW D: 5, aac, 100
with an example as above,
only ROW D will be returned since rows a,b,c PAGES (3) match the keyword count.
any help will welcome.
thx!
A solution without a subquery. This will work filne in Mysql, but for more strict SQL's you need to add some aggregate functios.
SELECT a.*
FROM mytable AS a
LEFT JOIN mytable AS b
ON b.keyword = a.keyword
GROUP BY a.id
HAVING COUNT(b.id) != a.pages
Also use indexes like these:
CREATE INDEX myindex ON mytable (keyword);
CREATE INDEX myindex2 ON mytable (pages);
select *
from table t1
where t1.pages <> (select count(*)
from table t2
where t1.keyword = t2.keyword)
But that's a a pretty slow query. Just to give you an idea...