Select 2-3 number combination from 5 column Table MySQL - php

Table structure:
MyTable (
ID INT AUTO_INCREMENT,
Num1 INT,
Num2 INT,
Num3 INT,
Num4 INT,
PRIMARY KEY(ID)
)engine=InnoDB;
Now i have around 20-30k records. Num1, Num2, Num3 and Num4 are just some random numbers. Im trying to select 2 and 3 number combinations from this table. For example lets say i have the following rows in table:
ID Num1 Num2 Num3 Num4
1 20 11 9 150
2 30 11 20 19
3 40 45 11 20
I would want to select the most frequently used 2 number combinations and then 3 number combinations. So note that 20 and 11 appear 3 times in table means the combination 20,11 or 11,20 doesnt matter the order has count 3 and so on for other combinations.
I want to retrieve this data in PHP array so that i can do some calculations or display on screen.
What i tried so far:
SELECT *
FROM MyTable
WHERE (Num1 = :num1 AND Num2 = :num2) OR (Num1 = :num1 AND Num3 = :num2) OR
(Num1 = :num1 AND Num4 = :num2) OR (Num2 = :num1 AND Num1 = :num2) OR
(Num2 = :num1 AND Num3 = :num2) OR (Num2 = :num1 AND Num4 = :num2) OR
***
***
and so on for all combinations. Now this gets annoying if i try to use it for 3 number combinations.
Is there a better and efficient way of doing this?
Do i need to restructure table to make this easier?
Will restructured table be normalized? (Right now i think is normalized if not please tell me)

Case 2 combinations
I think you should consider store information in a big matrix like this:
num times_appearing_with_number_1 times_appearing_with_number_2 ...
For a case like
1 8 2 3
1 7 23 24
it would be like:
num 1 2 3 4 5 6 ...
1 - 1 1 0 0 0 ...
2 1 - 1 0 0 0 ...
And then you check which lines have bigger numbers. The indexes would be useful to get the number it corresponds to.
Case 3 combinations
The same with a 3D-matrix.
To feed these tables you should only fetch the information from MySQL and then loop.

since the order of values doesn't matter, there are only 6 permutations to pick two out of four columns (c1-c2, c1-c3, c1-c4, c2-c3, c2-c4 and c3-c4), and only four permutations to pick three (c1-c2-c3, c1-c2-c4, c1-c3-c4, c2-c3-c4).
One approach would be to create a temporary table which contains the id of the row and all 6 (4 for three cols) permutations of those values. You could use a query like this:
SELECT id, CASE Num1<=Num2 WHEN TRUE THEN CONCAT(Num1,"-",Num2) ELSE CONCAT(Num2,"-",Num1) END FROM MyTable
UNION
SELECT id, CASE Num1<=Num3 WHEN TRUE THEN CONCAT(Num1,"-",Num3) ELSE CONCAT(Num3,"-",Num1) END FROM MyTable
...
All that's left then is counting the number of matching rows (note that above query could either be run manually or as a subquery to the counting query)
Edit: Something to fiddle with.

Related

Update 2nd duplicate value in mysql table?

i have 52k rows of records in my user table. In that table user_hash column having approximately 2000 duplicate values. i want to update user_hash columns 2nd duplicate value. The following table user_id (3, 10), (5, 14) having same value and i want to update user_id 10 and 14 values. how can i update it with MySQL Qry?
--------------------------------
user_id user_hash user_status
--------------------------------
1 ae57250b 1
2 310cb4e0 1
3 28b365c7 1
4 0073265b 1
5 8bec42a9 1
6 00a5c443 1
7 e1c27b19 1
8 993dc301 1
9 8fc8a6bf 1
10 28b365c7 1
11 194714c0 1
12 4611d83a 1
13 277a426b 1
14 8bec42a9 1
15 740c1412 1
... ... ...
... ... ...
... ... ...
The following qry which i have used to check duplicate entry
SELECT user_hash, COUNT(user_hash)
FROM user_data
GROUP BY user_hash
HAVING COUNT(user_hash) > 1;
The first thing that comes to mind is that you may want to define a constraint such that in the future you can't have non-unique values where you don't want them.
The second thing is to ensure that these hashes can't legitimately collide/overlap.
Those thoughts aside (as they may be irrelevant to your use case):
update user_data set user_data.user_hash = STORED_PROC_FOR_HASH()
from (
select *, row_number() over(partition by user_hash order by (select null)) row_num
from user_data
) user_data
where row_num > 1
Source for the above query: https://stackoverflow.com/a/25090251/3080207
As hinted at by Nick, you'll need to be able to generate a unique hash, which is pretty much the 2nd component to this problem.
Hopefully that is helpful.

trying to create a query when greater and less than inside the mysql table php

Look at my table below. When I have a value and cat, I want to check the id. If I have cat a and value 3, then I will get id 1, but if I get cat a and value 1, then return false, because value 1 is not greater than 2. The problem is that the greater sign is inside the table. I cannot figure a way to do it on mysql query, help please. I can alter the table value structure if need.
table
id cat value
1 a greater than 2
2 b less than 2
3 c less than 2
4 d greater than 5
$val = 3;
SELECT id FROM my_table WHERE value=$val and cat = a
table
id cat lbound ubound
1 a 2 2147483647 (Assuming signed int)
2 b -2147483648 2
3 c -2147483648 2
4 d 5 2147483647
$cat = 'a';
$val = 3;
SELECT id
FROM my_table
WHERE cat = $cat
AND lbound <= $val -- If you use nulls instead of default extreme values,
AND ubound >= $val -- then these two bounds comparisons will be more complicated
ORDER BY lbound DESC LIMIT 1 -- if overlapping ranges are possible
Design-wise I would prefer nulls for default "no bound" values, but expressions using OR's like AND (lbound IS NULL OR lbound <= $val), or functions like IFNULL(lbound,-2147483648) <= $val tend to disqualify index use.

Cross Calculation in SQL Server

I have a complicated request. I have to make a report in PHP like the picture below.
Part summarized yield must be filled with across calculation.
Like I explain in formula column, value in part summarized yield got from calculation between location yield and part summarized yield.
(See this formula)
How to do that calculation in a PHP report?
I already tried using a cursor, but it still did not work.
Here is my cursor calculation:
--In PHP file, i make query to insert data first to table tyield_summary
--Cursor to input yield_summary
Declare #nourut varchar(2), #maxnourut varchar(2), #bpnum varchar(20), #pnum varchar(20), #curnourut varchar(2), #psum decimal(18,2), #ysum decimal(18,2)
DECLARE StockCursor CURSOR
FOR
select no_urut, part_number, Part_Summary
from tyield_summary
where no_urut<>'99'
order by part_number desc, no_urut asc
set #bpnum=''
OPEN StockCursor
FETCH NEXT FROM StockCursor INTO #nourut, #pnum, #psum
WHILE ##FETCH_STATUS=0
BEGIN
if #bpnum=#pnum
begin
select top 1 #curnourut=no_urut
from tyield_summary
where part_number=#pnum
and no_urut<#nourut
order by no_urut desc
set #bpnum=#pnum
select #maxnourut = max(no_urut) from tyield_summary
where part_number=#pnum
update tyield_summary
set yield_summary = case when Part_Summary=0 then #psum else (Part_Summary*#psum)/100 end
where part_number=#pnum
and no_urut=#curnourut
end
else
begin
set #bpnum=#pnum
end
FETCH NEXT FROM StockCursor INTO #nourut, #pnum, #psum
END
CLOSE StockCursor
DEALLOCATE StockCursor
Here table structure :
I need to fill part_summary field using formula that i show in excel.
In formula show, calculation using cross field.
Here is how you can do it (without nasty cursors).
Just use row number over your ordering/aggregation criteria to find the next row,
left join each row with its next (not forgetting the aggregation criteria) and it's done.
Let's use an example (and here is how you properlu post a table structure):
create table Lazydude
(
Partno varchar(20) not null
,Seq int not null
,[Value] float not null
)
GO
insert into Lazydude (Partno, Seq, [Value])
values
('AAA', 1, 77.7)
,('BBB', 0, 2)
,('BBB', 3, 3)
,('BBB', 9, 5)
,('CCC', 1, 33.3)
,('CCC', 2, 33.3)
GO
and to select using row number and use the result in a self-join
with Temp as(
select Partno, Seq, [Value]
,ROW_NUMBER() OVER(ORDER BY Partno, Seq) AS [Row]
from Lazydude
)
select t0.Partno, t0.Seq, t0.[Value], t0.[Row]
, t1.row as [Next Row], t1.[Value] as [Next Value]
, case when t1.row is null
then t0.[Value]
else t0.Value * t1.Value
end as [The Calculation]
from Temp t0
left join Temp t1 on t1.[Row] = t0.[Row] + 1 and t1.Partno = t0.Partno
You can see the results in the SQL Fiddle
Partno Seq Value Row Next Row Next Value The Calculation
AAA 1 77.7 1 (null) (null) 77.7
BBB 0 2 2 3 3 6
BBB 3 3 3 4 5 15
BBB 9 5 4 (null) (null) 5
CCC 1 33.3 5 6 33.3 1108.8899999999999
CCC 2 33.3 6 (null) (null) 33.3

algorithm/query to get statistical data from table using php/mysql

I have the following table structure:
CREATE TABLE test(
myID INT,
num1 INT,
num2 INT,
num3 INT,
PRIMARY KEY (myID)
)engine=innodb;
now i have the following data in the table:
myID num1 num2 num3
1 15 27 98
2 27 38 66
3 15 27 77
now i need to run 2 queries, first query runs to select all numbers and on PHP side i count the number of times each number appeared (frequencies), the second query should select the second most frequent number.
First query:
$numfreq = PDO->prepare('
SELECT num1, num2, num3
FROM test
');
$numfreq->execute();
$allNums = array();
while ($row = $numfreq->fetch(PDO::FETCH_ASSOC)) {
$allNums[] = intval($row['num1']);
$allNums[] = intval($row['num2']);
$allNums[] = intval($row['num3']);
}
$numFrequencies = array_count_values($allNums);
arsort($numFrequencies);
this correctly returns frequencies of each number from the table. Now for the second part
THIS IS WHERE I NEED HELP:
I get the most frequent appeared number in this case its 27 since its frequency is 3, I need to select that 1 number that appears the most next to 27 means i need to get somehow number 15 since it appears twice next to 27.
i can probably figure out algorithm on PHP side but i was wondering if its possible to do it using query?
so the final result would be:
most frequent number: 27
most frequent number 27 combined with 15 appears 2 times and is most frequent combination.
select val, count(val) as frequency
from
(select num1 as val from test
union all
select num2 as val from test
union all
select num3 as val from test
) as b
group by val
order by frequency desc
limit 2
Sqlfiddle here.
The inner query converts the three columns into a result set with just one column - highlight the inner query, and you'll see how it works. We then use that result set as the source for the counting/ordering query.

PHP - SQL: fetching results in round robin fashion

I have a table, which consists of 3 fields:
id
name
status
Every time I get the results, it should give me 5 names whose status = 1.
Suppose the db contains following:
id name status
1 A 1
2 B 1
3 C 0
4 D 1
5 E 0
6 F 0
7 H 1
8 I 1
9 J 1
10 K 1
11 L 1
12 M 0
1st time, fetch should return: A,B,D,H,I (5 records)
2nd time, fetch should return: J,K,L,A,B (5 records)
UPDATE: I don't want typical pagenation. Consider I have 12 available names from A1 to A12. The first fetch should return A1-A5, second fetch A6-A10 and third fetch A11, A12, A1, A2, A3. So when I reach the end, I need to get records starting from the first to fill the 5 slots.
i am doing it in php with mysql
This looks like some sort of job allocation script?
You need 2 things:
the highest ID returned last time the script was run (lastID)
a number larger than the maximum ID in the table (bigNum)
Then you can write your query as
SELECT
id, name
FROM
table
WHERE
status=1
ORDER BY
(bignum + id) MOD (bigNum + lastID + 1)
LIMIT 5
Shazaam!
Keep track of the ids of the records returned, and for the following queries do:
select top 5 *
from (
select top 5 *
from MyTable
where status = 1
and id not in (1,2,4,7,8)
order by name
union
select top 5 *
from MyTable
where status = 1
order by name
) a
$q = mysql_query("SELECT name FROM table WHERE status = 1 LIMIT 5);
while ($row = mysql_fetch_row($q))
{
.... //first 5
}
$q = mysql_query("SELECT name FROM table WHERE status = 1 LIMIT 5,5);
while ($row = mysql_fetch_row($q))
{
.... //second 5
}
this uses the offset functionality of mysql- think of it as pagination for your results.

Categories