So, I have this MySQL table. Here are the relevant columns:
| raw line | composed_line | next_line
|----------------------|---------------|------------------------
| | | When I have a bad day,
| I cry my eyes out. | | When I cry my eyes out,
| I get ice cream. | | When I get ice cream,
| Things seem better. | | When things seem better,
| I get out of bed. | | When I get out bed,
I have this query, which does what I want it to do - it selects the data from the 'next line' column of the penultimate row and combines it with the data from the 'raw_line' column of the most recent row.
SELECT CONCAT((SELECT `next_line` FROM `lines` ORDER BY id DESC LIMIT 1 OFFSET 1),
(SELECT `raw_line` FROM `lines` ORDER BY id DESC LIMIT 1))
So the result looks like
When things seem better, I get out of bed.
However, all my attempts to take this result and insert it into a column called 'composed_line' of the most recent row have failed. I have tried using PHP and SQL to do this, none of which work.
I wouldn't need to do this if I could figure out a way to display (in PHP) the whoooole table with the 'next_line' and 'raw_line' concat'd and sorted by ID asc, but my attempts to do that have also been dismal failures, always displaying the 'next_line's together, then the 'raw_lines' together, or some other unwanted crappy result (doublesadface).
The result I would want would look like:
When I have a bad day, I cry my eyes out.
When I cry my eyes out, I get ice cream.
When I get ice cream, things seem better.
When things seem better, I get out of bed.
I am brand new to SQL. Any help would be much appreciated.
Assuming you have an "id" column, you'd be better off using it with a join:
update line a
join line b on a.id = b.id-1
set a.composed_line = concat(a.next_line,' ',b.raw_line)
where b.raw_line is not null;
or, to just display it:
select
concat(a.next_line,' ',b.raw_line)
from
line a
join line b on a.id = b.id-1
SQLFiddle here
SELECT CONCAT(nextlines.next_line, rawlines.raw_line) AS line
FROM `lines` rawlines
JOIN `lines` nextlines
ON rawlines.id = (nextlines.id % (SELECT COUNT(*) FROM `lines`)) + 1
ORDER BY rawlines.id ASC
See SQL Fiddle demo.
The only slightly complex bit is the modulus (%) with the number of records so that the last ID in rawlines will join to the first ID from nextlines.
Related
I have a games database and I need to create pairs of similar games in another table. So, let's say, game ID 5 and ID 12 need to be paired, which should be like this:
---------------------------
| PairID | First | Second |
---------------------------
| 1 | 5 | 12 |
---------------------------
So what I need basically is to join pairs and games tables and select and display data for all IDs of each pair depending on which game is being browsed. That is, if it's game ID 5 then ID 12 should be displayed and vice versa. Seems pretty trivial at first, except I discovered there is no neareast elegant solution to this, where the major problem is the order of IDs in the pairs table.
First of all, with this scheme I'm forced to use two separate joins of the 'games' table and select both games' data regardless like this:
SELECT simpairs.id, simpairs.first, simpairs.second,
games_one.id AS first_id, games_two.id AS sec_id,
games_one.title AS first_title, games_two.title AS sec_title,
games_one.year AS first_year, games_two.year AS sec_year
FROM simpairs
LEFT JOIN games AS games_one ON simpairs.first = games_one.id
LEFT JOIN games AS games_two ON simpairs.second = games_two.id
WHERE simpairs.first = <id> OR simpairs.second = <id>
Secondly, I need the script to pick out and display the correct data like this:
$id = $_GET['id'];
while($row = mysqli_fetch_assoc($res)) {
if($row['first_id'] != $id) {
$game_id = $row['first_id'];
$title = $row['first_title'];
$year = $row['first_year'];
} else {
$game_id = $row['sec_id'];
$title = $row['sec_title'];
$year = $row['sec_year'];
}
...
}
Ok, so this is already pretty messy. Still, the biggest issue is sorting the output alphabetically. Obviously, it can't be easily done on the SQL side unless the query is somehow rebuilt for which there is no apparent route as it must include an equivalent for PHP condition, or the pairs table should be modified to contain a mirrored pair for each new entry like this:
---------------------------
| PairID | First | Second |
---------------------------
| 1 | 5 | 12 |
---------------------------
| 2 | 12 | 5 |
---------------------------
This would work of course and I would only need 1 join instead of 2, which would also make sorting easier directly on the SQL side, yet this also doesn't seem very elegant as I would have to perform two inserts for each new pair instead of just 1 plus clutter the database with mirrored entries making it exactly 2 times larger. I mean, if this is the right way then I guess I'm fine with that.
Sorting data on the script side is no less daunting. Typically, arrays are used for the occasion, except this time around I don't see how it can be achieved effectively. I will need to store ID, game title and year of release somehow and then sort everything based on titles alone. Meaning, I should be probably using 2 dimensional arrays where titles act as parent keys for sub-arrays containing IDs and years, then I should somehow sort only the parent keys without affecting the sub-arrays and I really don't know how to do that nor if it's worth it at all. All in all, seems like unnecessary strain to both the database and the script.
So what would be the optimal solution here?
You have an id that relates to a game in the games table.
You have a table that links other game id's to the main game id
You want to show a list of those linked games and related info.
Select lg.*
FROM `games` g
LEFT JOIN `simpairs` s
ON s.first = g.id OR s.second = g.id
JOIN `games` lg // linked games
on lg.id = case when s.first = g.id then s.second else s.first end
where g.id = ?
Let me know if you have any questions, it's pretty self explanatory. Though it does assume simpairs never has reverse duplicate values in first and second otherwise you might need to filter those out.
I have a table like this
d_id | d_name | d_desc | sid
1 |flu | .... |4,13,19
Where sid is VARCHAR. What i want to do is when enter 4 or 13 or 19, it will display flu. However my query only works when user select all those value. Here is my query
SELECT * FROM diseases where sid LIKE '%sid1++%'
From above query, I work with PHP and use for loop to put the sid value inside LIKE value. So there I just put sid++ to keep it simple. My query only works when all of the value is present. If let say user select 4 and 19 which will be '%4,19%' then it display nothing. Thanks all.
If you must do what you ask for, you can try to use FIND_IN_SET().
SELECT d_id, d_name, d_description
FROM diseases
WHERE FIND_IN_SET(13,sid)<>0
But this query will not be sargable, so it will be outrageously slow if your table contains more than a few dozen rows. And the ICD10 list of disease codes contains almost 92,000 rows. You don't want your patient to die or get well before you finish looking up her disease. :-)
So, you should create a separate table. Let's call it diseases_sid.
It will contain two columns. For your example the contents will be
d_id sid
1 4
1 13
1 19
If you want to find a row from your diseases table by sid, do this.
SELECT d.d_id, d.d_name, d.d_description
FROM diseases d
JOIN diseases_sid ds ON d.d_id = ds.d_id
WHERE ds.sid = 13
That's what my colleagues are talking about in the comments when they mention normalization.
Not sure how to explain this exactly but here goes.
I have these tables:
messages:
------------------------
|msgid|clientid|message|
------------------------
|1 |536 |Hello |
------------------------
|2 |543 |Hello |
------------------------
|3 |529 |Hello |
------------------------
clients:
----------------------
|cleintid|wholesaleid|
----------------------
|536 |479 |
----------------------
|543 |480 |
----------------------
|529 |479 |
----------------------
I want to only pull records from the messages table if the client id in the message record is owned by clients.wholesaleid = 479.
So that should pull records 1 and 3 from the messages table.
I know how to do with with completely separate multiple nested queries but I know there is a smarter way to do this with pure SQL in one query. I have been putting on learning this for way too long so I am here to figure this out.
Normally what I would do in this instances is do a simple query and loop through the clients table looking for all client id's that match the wholesale ID. I would stuff them all in an array or, as I loop through them, do a separate query for all messages for that one client id. It's gross and I know there is a better way. Tons of loops, within loops and slow as heck if my data set gets large.
I know this isn't correct but I am hoping it will help illustrate what I am trying to do.
Something like this but without multiple loops:
SELECT * FROM clients WHERE wholesaleid = 479;
For Each Loop Here
SELECT * FROM messages WHERE clientid=ThisClientID
For Each Loop #2 HERE
Print msgid, clientid, message
End For Each Loop #2
End For Each Loop
Sorry this is so confusing, just not sure how to better explain how I do it now and where I am trying to get.
I am guessing everyone will tell me to go learn JOINS but, I have spent plenty of time on that and I am not sure how it applies if at all for what I am trying to accomplish.
Use INNER JOIN(cleintid in table clients might be a typo in your question):
SELECT messages.*
FROM messages
INNER JOIN clients
ON messages.clientid = clients.cleintid
AND wholesaleid = 479;
SQLFiddle Demo
YOU CAN JOIN THOSE TWO TABLE
SELECT m.*
FROM messages m
INNER JOIN clients c
ON m.clientid = c.clientid
AND c.wholesaleid = 479;
I have a MySQL query that results in something like this:
person | some_info
==================
bob | pphsmbf24
bob | rz72nixdy
bob | rbqqarywk
john | kif9adxxn
john | 77tp431p4
john | hx4t0e76j
john | 4yiomqv4i
alex | n25pz8z83
alex | orq9w7c24
alex | beuz1p133
etc...
(This is just a simplified example. In reality there are about 5000 rows in my results).
What I need to do is go through each person in the list (bob, john, alex, etc...) and pull out a row from their set of results. The row I pull out is sort of random but sort of also based on a loose set of conditions. It's not really important to specify the conditions here so I'll just say it's a random row for the example.
Anyways, using PHP, this solution is pretty simple. I make my query and get 5000 rows back and iterate through them pulling out my random row for each person. Easy.
However, I'm wondering if it's possible to get what I would from only a MySQL query so that I don't have to use PHP to iterate through the results and pull out my random rows.
I have a feeling it might involve a BUNCH of subselects, like one for each person, in which case that solution would be more time, resource and bandwidth intensive than my current solution.
Is there a clever query that can accomplish this all in one command?
Here is an SQLFiddle that you can play with.
To get a random value for a distinct name use
SELECT r.name,
(SELECT r1.some_info FROM test AS r1 WHERE r.name=r1.name ORDER BY rand() LIMIT 1) AS 'some_info'
FROM test AS r
GROUP BY r.name ;
Put this query as it stands in your sqlfiddle and it will work
Im using r and r1 as table alias names. This will also use a subquery to select a random some_info for the name
SQL Fiddle is here
My first response would be to use php to generate a random number:
$randId = rand($min, $max);
Then run a SQL query that only gets the record where your index equals $randID.
Here is the solution:
select person, acting from personel where id in (
select lim from
(select count(person) c, min(id) i, cast(rand()*(count(person)-1) +min(id)
as unsigned) lim from personel group by person order by i) t1
)
The table used in the example is below:
create table personel (
id int(11) not null auto_increment,
person char(16),
acting char(19),
primary key(id)
);
insert into personel (person,acting) values
('john','abd'),('john','aabd'),('john','adbd'),('john','abfd'),
('alex','ab2d'),('alex','abd3'),('alex','ab4d'),('alex','a6bd'),
('max','ab2d'),('max','abd3'),('max','ab4d'),('max','a6bd'),
('jimmy','ab2d'),('jimmy','abd3'),('jimmy','ab4d'),('jimmy','a6bd');
You can limit the number of queries, and order by "rand()" to get your desired result.
Perhaps if you tried something like this:
SELECT name, some_info
FROM test
WHERE name = 'tara'
ORDER BY rand()
LIMIT 1
i am using this code so i can count the number of comments for each article
SELECT *, COUNT(comment_id) as count
FROM article_comments
WHERE article_id =colname
GROUP BY article_id
this is what my comment table look like
http://i54.tinypic.com/2cdu3dk.png
i want to save these number in another table (the articles table.. each number next to it's article ) like this
http://i54.tinypic.com/2dgm82u.png
and when the user enter a comment..the number change automatically
someone help me with the code
or if there is another way to do this
i know it's a long question
but i have been trying to solve this for like..forever
thanx
You could set a TRIGGER that updates the comment count table every time a comment is added. Or you could simply add the UPDATE query right after the INSERT query in your comment page.
You probably do not need a lookup table. 1 article has many comments. Therefore, structure your comments table something like this (add an article field);
id | article | content
-------------------------
1 | 1 | Comment 1 for article 1.
2 | 1 | Comment 2 for article 1.
3 | 2 | Comment 3 for article 2.
When displaying your article, list comments using the following query;
SELECT a.id, a.content FROM articles a WHERE a.article = :myArticleId
When creating a new comment:
INSERT INTO comments (article, content) VALUES (:currentArticleId, :content)
UPDATE article SET commentCount = commentCount + 1 WHERE article = :currentArticleId
The articles table will look something like this;
id | commentCount | content
------------------------------
1 | 0 | Article with 0 comments.
2 | 3 | Article with 3 comments.
This requires some work on your part, but it has more benefits than drawbacks.
Your proposed solution has 2 large drawbacks;
COUNT() in SQL does not scale very well and can be slow, normally it can be avoided.
The lookup table adds unnecessary complexity to your application.
Triggers should also always be avoided. They create "magic" conditions - your database can be changed without you knowing about it. Triggers are often more difficult to change than code too.
$query = mysql_query("SELECT * FROM article_comments WHERE article_id =".$youarticleId);
//the number of comments is :
$number_Of_Comments = mysql_num_rows($query);
//save it to another table
$query2 = mysql_query("UPDATE yourTable set numberOfComments =".$number_Of_Comments);
on saving comments, try to:
update table_where_you_count_the_comments set number_of_comments = number_of_comments +1 where article_id = theID limit 1;
or look for mysql triggers.
you're asking the sql server to select everything and the count id at the same time, use one of them and give it a where close, and Bingo!