Select *, count(*) in one Query [duplicate] - php

This question already has an answer here:
SQL counting all rows instead of counting individual rows
(1 answer)
Closed 5 years ago.
I've got a DB with a few columns and I'm trying to populate a html table with it.
Everything's going fine but I've encountered the following problem:
Since I'm filling filtered Results into different Columns, I came up with a SQL Query that needs both Select * and count(*)?
$query = "SELECT *, COUNT(example_A) AS total_example_A FROM test WHERE example_A = 'certain_result' AND date(start_date) = '$current_date_proof' ORDER BY start_date ASC";
It does work, but I'm only getting the first result. I guess I cannot combine Select with Count?

You can do it with a correlated sub-query, Count is an aggregation function ( so it aggregates or combines all the data ):
$query = "
SELECT
t1.*,
( SELECT COUNT(t0.id) FROM test AS t0 WHERE t0.id = t1.id ) AS total_example_A
FROM
test AS t1
WHERE
t1.example_A = 'certain_result'
AND
date(t1.start_date) = '$current_date_proof'
ORDER BY t1.start_date ASC
";
This assumes that your table test has a primary key named id. One other thing is I would count on the primary key if its not (example_A) COUNT(t0.id)
In my world a database either have a Auto Increment Int as the primary key or they have a compound primary key consisting of 2 or more foreign keys which are themselves Auto Increment Int fields. It's vital ( IMO ) to always have a surrogate key in you table. That is a key that has no direct relationship to the data itself. But, that is just me...
You could just count the return within your application, but barring that the correlated sub-query should give you the best/goodest performance. Certainly much better then a separate database call.

Related

Getting the most recent message in every conversation [duplicate]

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 3 years ago.
I have a message table :
CREATE TABLE OneToOneMessages (
MessageID int NOT NULL AUTO_INCREMENT,
AuthorID int NOT NULL,
RecipientID int NOT NULL,
MessageText TEXT,
SentTime DATETIME,
PRIMARY KEY (MessageID),
FOREIGN KEY (AuthorID) REFERENCES Users(ID),
FOREIGN KEY (RecipientID) REFERENCES Users(ID)
);
I need to get the latest message from every conversation in order. I've found some queries online but I have no idea how they work and am not sure they get the job done.
I think I could just go one by one, getting the last message from each conversation and then sorting them by the sent time. If there was one query I could use that gets all the information, that would be best.
You can use a NOT EXISTS condition with a correlated subquery to filter the table. The condition ensures that no other record exists with the same sender/recipient or recipient/sender tuple and a greater send time:
SELECT t.*
FROM OneToOneMessages t
WHERE NOT EXISTS (
SELECT 1
FROM OneToOneMessages t1
WHERE
(
t.AuthorID = t1.AuthorID AND t.RecipientID = t1.RecipientID)
OR t.RecipientID = t1.AuthorID AND t.AuthorID = t1.RecipientID
)
AND t1.SentTime > t.SentTime
)
If you are using MySQL 8.0, this can be done potentially more efficiently using window function ROW_NUMBER():
SELECT *
FROM (
SELECT
t.*,
ROW_NUMBER() OVER(
PARTITION BY LEAST(AuthorID, RecipientID), GREATEST(AuthorID, RecipientID)
ORDER BY SentTime DESC
) rn
FROM OneToOneMessages t
)x
WHERE rn = 1
The inner query ranks records by descending send time within groups of records having the same sender/recipient or recipient/sender tuple. The outer query filters only on the top record in each group.

How do I delete duplicate rows in SQL? [duplicate]

This question already has answers here:
Remove duplicate rows in MySQL
(26 answers)
Closed 7 years ago.
I am trying to delete duplicate rows using SQL, whilst leaving one of the rows behind.
The table I am trying to delete duplicate rows from is called table "A" made up of:
A.AID, A.BID, A.AName, A.AType, A.APrice.
In this table I have a number of duplicate rows with all of the data exactly the same apart from the A.ID.
I am trying to create a query that will look for duplicates and then remove the duplicate making sure one of the rows are left behind. I am using phpMyAdmin and MySQL.
DELETE FROM member
WHERE id IN (SELECT *
FROM (SELECT id FROM member
GROUP BY member_id, quiz_num, question_num, answer_num HAVING (COUNT(*) > 1)
) AS A
);
use group by and count
DELETE FROM
YourTable
WHERE
AID NOT IN ( SELECT
MAX(AID)
FROM
YourTable
GROUP BY
BID ,
AName ,
AType ,
APrice );
Consider the query below, this will remove all the duplicate rows and prevents any future duplicate row.
ALTER IGNORE TABLE A ADD UNIQUE INDEX index_name (A.AID, A.BID, A.AName, A.AType, A.APrice );

How to find the next available integer in MySQL table using PHP

I know auto_increment is the way to go but I can not use auto_increment feature since the column in my table might repeat, its not unique. When I insert a new row to a table I need a way to find the next available spot to insert it.
For example table structure:
Primary Key = (ID, UserID)
ID UserID
3 6
3 1
1 3
Now when i do insert query i want to isert it at ID = 2 and not 4. With auto_increment it gives me 4
Is there a solution without using the loop in PHP? So far what i have is I fetch all rows into array and then find the next available digit in ID. Is it possible to do this without fetching all rows in PHP and just doing it on MySQL query ?
SELECT t1.id+1 AS MISSING_ID
FROM the_table AS t1
LEFT JOIN the_table AS t2 ON t1.id+1 = t2.id
WHERE t2.id IS NULL
ORDER BY t1.id LIMIT 1;
I made a fiddle: http://sqlfiddle.com/#!2/4d14d/2
No, it is not possible without processing the data. The preferred method to correct this issue is to adjust your table structure to support a unique, auto-incrementable field. Failing that, you will have to process the data (either in PHP or via an SQL statement) to find an open slot.
This should do the trick:
SELECT
min_table.ID+1 AS start,
MIN(max_table.ID) - 1 AS end
FROM
your_table AS min_table,
your_table AS max_table
WHERE
min_table.ID < max_table.ID
GROUP BY
min_table.ID
HAVING
start < MIN(max_table.ID)
The left hand column will return the first available spot in the sequence gap, and the second is the highest number in that particular gap.
Source: http://www.codediesel.com/mysql/sequence-gaps-in-mysql/
My workaround for not loaded project:
Suppose, you have questionset with question_id 's which belong to certain topic_id.
Suppose, user navigates and clicks "<Prev" "Next>" buttons to navigate questions.
You have only current id. Catching the direction of navigation, topic_id, question_id you can do a loop
do {
// query base, doing question_id++ or question_id-- depending on needed direction until you find next id within topic_id
} while( id!=null ) `
using incrementation or decrementation depending on direction of your move

UPDATE certain row in SELECTED items with Certain id

I need to Select a column with name song_number where id = 2 and then update the second row from the selected rows with 7 for example
what i think that the query i need is something like this but i can't get it work
UPDATE `song` SET `song_number`= 7 WHERE (SELECT `song_number` FROM `song` WHERE `id` = 2 LIMIT 1,1)
any help will be appreciated
edit: i think the problem is mainly in the database structure i made however i found a solution to what i need by making stored procedure http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
so that i can save the selected items in a procedure and then update it
You have to identify which row you want to update. Identification means using a UNIQUE key or the PRIMARY key of the table.
The limitation of MySQL on UPDATE can be lifted by moving the condition from the WHERE to a JOIN:
UPDATE
song AS s
JOIN
( SELECT PK --- the Primary Key of the tba;e
FROM song
WHERE id = 2
ORDER BY ---whatever
LIMIT 1 OFFSET 1
) AS u
ON u.PK = s.PK
SET s.song_number= 7
If the PRIMARY KEY is id, then the above is useless of course. You are doing something wrong.
I doubt it is possible with one query and yet I see no reason in doing it in one query.
Why can't you just select and then update?
I think should be like this:
UPDATE `song` SET `song_number`= 7 WHERE `song_number` = (SELECT `song_number` FROM `song` WHERE `id` = 2 LIMIT 1,1);

SELECT from various tables, with a list of indexes

Here is the scenario.
I'm developing a timeclock system; I have these tables:
-punch (id_punch,date)
-in1 (id_in1,time,id_punch,...)
-in2 (id_in2,time,id_punch,...)
.
-in6 (id_in6,time,id_punch,...)
-out1 (id_out1,time,id_punch,...)
-out2 (id_out2,time,id_punch,...)
.
-out6 (id_out6,time,id_punch,...)
My question is, how can I with only one query in PHP to get all values from in and out table, from a list of id_punch values, for example:
Get all punchs of September, or
Get all punchs of July to December,
I mean... from a list of id_punch between two dates, get all the results from the in, out table.
The only way I think is to do a query with each id_punch variable, but in a month its about 20-25 queries... to much?
To get all the data from the tables you'll need to join them with JOIN MySQL JOIN
But from what I can gather by looking at you tables, you probably should be thinking about making this into one table rather than the multiple tables you have here.
You really need to store all the in/out data in one table that is a child of punch:
CREATE TABLE punch (
id_punch SERIAL PRIMARY KEY,
punch_date DATE NOT NULL,
ip_address INT UNSIGNED NOT NULL
-- plus other attributes
) ENGINE=InnoDB;
CREATE TABLE inout (
id_punch BIGINT UNSIGNED,
in_time TIME NOT NULL,
out_time TIME NULL,
PRIMARY KEY (id_punch, in_time),
FOREIGN KEY (id_punch) REFERENCES punch (id_punch)
) ENGINE=InnoDB;
Now you can query very easily for all punches in September:
SELECT *
FROM punch LEFT OUTER JOIN inout USING (id_punch)
WHERE EXTRACT(YEAR_MONTH FROM punch_date) = '200909';
Your database schema is a little unclear, but if you're asking how to get the results corresponding to a list of ids you already have this should work (assuming your ids are 1,3,5,7,9)
SELECT * FROM table1, table2, table 3
WHERE table1.punch_id = table2.punch_id AND table2.punch_id = table3.punch_id AND table3.punch_id IN (1,3,5,7,9)
you'll probably need to modify it just make sure every table's punch_id is joined to that IN constraint
I can't use one table cause i have some informations in each punch, as ipaddress, and other information.
Neil, the answer was in my nose, i already saw a solution like yours, but my doubt is how to put the list in the query, answer for my own question = use a foreach() in php to "populate" this list...
Something like:
> SELECT * FROM table1, table2, table 3 WHERE table1.punch_id = table2.punch_id AND table2.punch_id = table3.punch_id AND table3.punch_id IN (<? foreach($query->results() as $row) echo $row->id_punch;?>)
im using codeigniter

Categories