MySql: Get number of row from query where id matches - php

I have a complicated select like:
select id from table
left join...
left join... (a lot of joins)
where ... (a lot of ANDs and ORs)
order by... (a lot of orders)
and I'm getting a result like:
1234
5565
7212
2212
etc.
I have an id which belongs to the result-set, like 7212, and want to know which row in the result-set matches the id (starting with row 0 this would be row 2 in my example).
Right now I'm reading all data and compare it in php, but I was wondering if there is a SQL-statement which does that for me and results 2 when entering 7212.
In fact I want to get the previous and next ids (row 1 and row 3 = 5565 and 2212), if thats somehow possible in 1 query that would be even better.

You can select the number row:
select #rownum:=#rownum+1 No, foo, bar from table, (SELECT #rownum:=0) r;
It's a possible duplicate of the question asked here: How to show sequential number in MySQL query result

Add an auto_increment index for each selected rows:
SELECT
#i:=#i+1 as index,
id
FROM table, (SELECT #i:= 0) AS i
LEFT JOIN...
LEFT JOIN...(a lot of joins)
WHERE ... (a lot of ANDs and ORs)
ORDER BY... (a lot of orders)
Give you this:
index id
1 1234
2 5565
3 7212
4 2212

Related

SQL - Select ALL rows that are LIKE%...% of each other (All Similar Rows)

For example, lets say in column source I have the following entries
SourceFileEmbed122
SourceFile1333
SourceItem13366
PreLoadSource7755
And I do a query of SourceFile it should match row 1 and 2 and show me all the column data for that row, but if I search for example: PreLoadSource or SourceItem it shouldnt show anything, as there is only 1 row that has a similar entry.
Kinda like an if contains sort of thing.
Basically, I want to do something like:
SELECT source, COUNT(*) TotalCount FROM sources GROUP BY source HAVING COUNT(*) > 1 ORDER BY COUNT(*) DESC
But the query does LIKE instead of LIKE%...% (Like in PHPMyAdmin) which results in it only matching EXACT matches of each other, so stuff like:
row123/
row123
Wont match each other and will be ignored. But I want this to MATCH basically if row123's full text is ALSO all in another row's value, then match.
Lets say I have:
http://link.ext/dir123/file.mp3
http://link.ext/dir123
http://link.ext/dir123/file2.mp3
http://link.ext/dir123
The query should match .../file.mp3, .../file2.mp3 and ../dir123 because row 2 http://link.ext/dir123 is also in row 1, 3 and 4.
One way is doing a inner join with the same table,
if you need a simple count you can do something like that:
SELECT s1.source, COUNT(*)
FROM sources s1
INNER JOIN sources s2
ON s1.id <> s2.id AND s1.source LIKE CONCAT('%', s2.source, '%')
GROUP BY s1.source
One way to test for at least two matches is:
select s.*
from sources s
where s.source like '%<whatever>%' and
exists (select 1
from source s2
where s2.source like '%<whatever>%' and
s2.source <> s.source
);

LIMT query to 1 if selcted two tables

How to limit query to 100 if i have selected data from two tables.
But i want the limit 100 to only work on one of them.
SELECT c.* , p.*
FROM test c,test2 p
WHERE c.id=p.id_puf
LIMIT 100
But here is the tricky part(at least for me)
In table "test" ja hold names.
Structure:
ID, Name, Age
Table "test2" ja hold record of the persons and they are connected with user ID
Structure:
ID, connect(this is same as "test" id), numbers
Now every tabel row in "test" is unique
I want to get all the results for test but all the record from the "test2".
Here is how you would do it -- select the items from the first table you want and then join to the 2nd table.
SELECT *
FROM (
SELECT *
FROM test
LIMIT 100
) c
LEFT JOIN test2 p ON c.id=p.id_puf
Notice I'm using "modern" joins. The join style you were using is about 20 years out of date and is not as good. It is much clearer how to solve this problem if you are using modern joins (for example).

Having max of column repeat for each row in mysql

Lets say I have a table A ,
A
user count
a 4
b 1
c 3
d 2
I want to write a query which returns each value of A along with max value of count,something like
user maxCount
a 4
b 4
c 4
d 4
The way I am trying to achieve this is,
select user,max(count) as maxCount from A
The result which I get is :
user maxCount
a 4
Which is clearly not what I want.
I understand I could write multiple queries(i.e. 'select user from A' /'select max(count) from A') as this may seem redundant ,
but I think having it this way would be best for me as I don't want to call mysql multiple times and also I push the returned data as a single jsonObj to the front end , so it is easier to have a single table then combing two returned-tables into one and than converting into json
This query will give you the max value on all rows:
SELECT user,
(SELECT MAX(count) FROM yourTable) AS maxCount
FROM yourTable;
Try this:
select user,max(count) as maxCount from yourTable group by user
That will get your your max counts, and group them by whatever unique values are in the user column.

MySQL Inner Join Returning Multiples of the Same Row

I have two MySql Tables as follows:
resource
-----------------------------------------------
id name group owner_id
-----------------------------------------------
1 MyResource1 hs 11
2 MyResource2 ms 24
3 MyResource3 ps 11
...
resource_access
-----------------------------------------------
id resource_id user_id
-----------------------------------------------
1 1 12
2 2 24
3 2 11
4 3 15
...
Now, the first table is a list of resources, of course, and their respective owners in the owner_id column. The second table is the result of "sharing" this resource with another user. The table resource_access may contain records with a user_id that is equivalent to the owner_id in a row of the resource_access as a result of messy cleanup from an owner exchange.
I simply want to get the id, name, and group of any resource that a user has access to, whether they are the owner or it has been shared with them. Here is my MySQL query for an example user (24):
SELECT resource.id, resource.name, resource.group
FROM `resource`
INNER JOIN resource_access ON (
resource.owner_id='24'
OR (
resource_access.user_id='24' AND
resource_access.resource_id=resource.id
)
)
Right now, it returns the id, name, and group for resource number 2 multiple times (like twelve). Is there a possible cause for this? I have tried LEFT and RIGHT joins and am getting the same result. There are many records in the resource table, but none with the id of 2. There are no duplicate rows in resource_access sharing the resource with the same user twice.
Thanks in advance.
Use:
SELECT DISTINCT resource.id, resource.name, resource.group
to remove duplicates.
The way an inner join conceptually works is that it produces a full cross-product between the two tables. This cross-product contains a row for each pair of rows in the input tables. Then it keeps the rows that match all the ON and WHERE conditions, and returns this as the result set. If there are multiple matching rows between the two tables, you'll get multiple rows in the result set.
If you were selecting columns from both tables, you would see that they're not actually the same row. They just have the same data from the resource table, but different data from the resource_access table. But you're not showing those latter columns in your result. Using DISTINCT merges all these rows in the result.
Because you are only selecting from the resource table, I would suggest putting the conditions in the where clause rather than using an explicit join:
SELECT r.id, r.name, r.group
FROM `resource` r
WHERE r.owner_id='24' or
EXISTS (select 1
from resource_access ra
where ra.resource_id = r.id and
ra.user_id = '24'
);
With this logic, the "join" cannot product duplicates.
Select the ownership of resources then union it to resources with access.
Resulting user_id column that is different from your WHERE RA.user_id value just means that resource was shared to them instead of them owning the resource. Hope this helps.
SELECT resource.name,resource.group,resource.owner_id AS user_id
FROM resource
WHERE resource.owner_id = '11'
UNION
SELECT R.name,R.group,R.owner_id AS user_id
FROM resource_access RA
LEFT JOIN resource R
ON (R.id=RA.resource_id)
WHERE RA.user_id = '11';

want to fetch first 9 records and make one more record which will be as “Others” in mysql

I am fetching records from one table with count of one field with other field as name. I want only 10 records. out of which 9 records give me field and its count. but i want to show 10 record as "Others" with all remaining fields with count. This is something like wrapping records.
Something like below will be table contents.
emp_id | designation
1 | software Engg.
2 | software Engg.
3 | Project Manager
not less than 10 designation.
And I want to show first 10 records as
Software Engineers 20
Project Manager 5
....
....
....
Others 50
Is there any way to make SQL Query for mysql db. So that it will be fast and save time in application level where I am adding up record counts for "Others". Or Suggest me how I can make it possible in effective way.
Try this:
SELECT IF(rowNum <= 9, designation, 'Other') designation, SUM(cnt)
FROM (SELECT designation, COUNT(*) cnt, (#row := #row + 1) rowNum
FROM contents, (SELECT #row := 0) dm
GROUP BY designation
ORDER BY designation
) d
GROUP BY IF(rowNum <= 9, designation, 'Other')
Change the GROUP BY and ORDER BY however you decide what 9 to show.
you can use SQL_CALC_FOUND_ROWS option in your query which will tell MySQL to count total number of rows disregarding LIMIT clause. You still need to execute a second query in order to retrieve row count, but it’s a simple query and not as complex as your query which retrieved the data.
Usage is pretty simple. In you main query you need to add SQL_CALC_FOUND_ROWS option just after SELECT and in second query you need to use FOUND_ROWS() function to get total number of rows. Queries would look like this:
SELECT SQL_CALC_FOUND_ROWS name, email FROM users WHERE name LIKE 'a%' LIMIT 10;
SELECT FOUND_ROWS();

Categories