Building a MYSQL query based on multiple unique listings - php

Sorry for the crappy title - didn't know how else to say it.
I have a commenting database where anyone can report a comment for abuse (anyone as in not just logged in members). This obviously means a person could report a comment multiple times. Where I need help is building a query that shows the number of times a comment has been reported but by unique email address AND ip address.
I'm not sure if that is clear or not -- if joe#joe.com of IP address 1.2.3.4 reports a message more than once, it will only count as one report. If there is an additional record of joe#joe.com with an IP of 4.5.6.7 reporting the same comment, it would count as two reports since the IPs are different.
The fields, all in one table:
id
comment_id
note
email
ip_address
I hope that all makes sense and any help would be GREATLY appreciated!

SELECT email, ip_address, COUNT(DISTINCT note)
FROM log
GROUP BY
email, ip_address
Update:
As per your comment, I believe you want this:
SELECT comment_id, COUNT(DISTINCT email, ip_address)
FROM log
GROUP BY
comment_id

SELECT
comment_id,
COUNT(DISTINCT CONCAT(email,'|',ip_address))
FROM log
GROUP BY comment_id
As OMG Ponies said, adding a unique in email+ip_address would help, possibly with this to prevent lost notes:
INSERT INTO log (...) VALUES (...) ON DUPLICATE KEY note = CONCAT(note,' ',VALUES(note));

Related

Visiting count and IP address verification

I searched everywhere, any online tutorials, but they are all dated and badly composed. I was looking for a way to count visits to a particular post, but only unique visits via ip address.
I am not unfortunately an expert, I have tried some ways but without success.
So I asked how to do it?
I create a table in the database called "views_post" with the various fields: ip_address, id_post, views_count.
I should create insert or update queries that add +1 to the "views_count" field of the specified post ID. Let's verify if an IP address is already present, so it will not insert / update the table.
I do not know how to run it all, I did some tests but only put the first value but it does not update anything at the next visits.
Any advice is welcome, thank you.
You don't need an update .. you could simply add each single access to a table visit
id_address,
id_post,
date_visit
and if you need distinct count for post you could use count(distinct ip_address) total or by date eg:
select id_post, count(distinct ip_address)
froom my_table_visist
group by id_post
or
select date_visit, count(distinct ip_address)
froom my_table_visist
group by date_visit

Building a SQL query - Return some rows once, some not

I need to build a SQL query which is beyond my programming abilities.
Okay, here is my request:
Let's say I have a table, with: id, user_id, email and amount columns. This query, should SELECT user_id only once! If I have matched user_id once, the query shall continue, but if the same user_id is matched again in another row, we should skip it.
Here comes the main problem...
Imagining that we grabbed user_id once, and skipped all same other rows with that user_id, now I need to sum all the contents from the amount column for the same user_id.
I think I complicated this a bit, I'll try illustrating my issue:
If this problem is not solvable via SQL only, then a PHP answer would work too.
I'm trying to create a list of users (no duplicate users) and add the amount they paid.
According to the image, user_id 56 paid 90.00 (12 + 45 + 33)
Can someone tell me a way how to achieve this?
Assuming the name of the table is users
SELECT user_id, email, SUM(amount) FROM users GROUP BY user_id

PM system - previewing previous PMs

I am working on a PM system where I'd like to have the previous sent PMs for one conversation, listed above the last received PM. But my question is: how do I go about setting up such a table in a database? I toyed for a while about using an id for each specific conversation, but what would the source for that id be? I can't use auto increment (it seems), because I'm using it for the primary "id" column.
Or maybe there's a completely different way I can experiment with the already available columns (id, from, to, subject, message, sent, read, deleted); but how? Please help a lost man out.
You could add a origin_id column to your table that contains the id of the root/original message, or NULL if it's a new discussion (root).
Then you can get the root messages by filtering those than have origin_id = NULL and then group by origin_id to get the message thread.
Okay, so I have got it partly solved...
I used another table containing the one column which holds the subject of the PM. I also have a new column in the regular "pms" table that holds the same ID to be able to join the tables together.
However, when I select all the PMs to show them in the inbox, I have not found a way to group the conversations in order by if they're read or not. I'm currently using this SQL query:
SELECT *
FROM `pms`
JOIN `pm_conversations` ON (pms.ConvID = pm_conversations.ID)
WHERE pms.To='username'
GROUP BY pm_conversations.ID
ORDER BY pms.ID
I came up with this:
SELECT MAX(pms.ID) as pmIDS,
pms.*,
pm_conversations.*
FROM `pms`
JOIN `pm_conversations` ON (pms.ConvID = pm_conversations.ID)
WHERE `To`='".$UserActive."'
GROUP BY pm_conversations.ID
ORDER BY pmIDS DESC

Preventing second votes in Comment Voting

Hi I have a question regarding a method to prevent second voting in a website where people can vote up or vote down a comment. Like Stackoverflow!! :)
The question is how I can keep track of whether a comment has already been voted by a logged in user. Lets assume this is for a online ecommerce store with reviews on products. Here's what I think:
All reviews data is stored in a table called 'reviews'
Field names: review_id, product_id, user_id, title, description, time_created, up_votes, down_votes, up_voters, down_voters
up_votes and down_votes contain the number of votes voting it up or down
up_voters and down_voters contain the user_id of the people who voted up or down in the format 1101.1102.1103 for users with user_id 1101, 1102 and 1103.
When a person clicks on the up vote button, the system will check if the current user's user_id matches anyone in up_voters. An explode function will turn 1101.1102.1103 into an array and in_array() will be used to check if the user has already voted.
Is there a better way to go about doing this?
That table will give you nightmares down the line. Just think of a hit product with 1K up_voters, your field will be 10K*4 characters long! Not just that, it will hinder your ability to make reports and study the data etc.
I don't know much about your needs but from what I can see in your table, I'd suggest the below.
review
user_id, product_id, type_of_vote, title, description, time_created
Use above table and use user_id, product_id as the key
OR
review
review_id, product_id, title, description, time_created
vote
review_id, user_id, type_of_vote
There are n number of ways to design tables for this. If it is an Operational Data Store(ODS) then you might want to normalize your design. If it's a warehouse then you may consider first table I mentioned above.

Query for private messaging system

I'm making private messaging system using mysql. Created this tables:
1) users (id, name)
2) messages(id, text, created)
3) user_has_messages(id, user_id, message_id, is_sender)
Table user_has_messages stores messaging history, so there are 2 rows(for "sender" user and for "receiver" user.) per 1 message. 2 rows per message because sender should see his message even if receiver deleted it.
So i need to fetch list of all dialogs for concrete user with last message in it. It should be easier to understend if you take a look a this pic: Explanation
The problem is that i cannot construct a proper query for this task. Maybe bad db design?
Looks like this query is what i need:
SELECT * FROM users_has_messages uhm1
WHERE uhm1.message_id=(
SELECT message_id FROM users_has_messages uhm2
WHERE (uhm1.receiver_id=uhm2.receiver_id AND uhm1.sender_id=uhm2.sender_id)
OR uhm1.receiver_id=uhm2.sender_id ORDER BY message_id DESC limit 1)
AND user_id=1
I believe the database design may be wrong, because if the recipient deletes his message (by deleting the user_has_messages row) then the sender can no longer see who they sent it to - information is lost.
If a message always has one sender and one recipient, then I would have the tables like:
1) users (id, name)
2) messages(id, text, created, sender_id, recipient_id,
deleted_by_sender, deleted_by_recipient)
Even with this simplified design the SQL for your requirement is a bit complicated:
select m.recipient_id, m.text
from messages m
where m.sender_id = ?
and m.created = (select max(created)
from messages m2
where m2.sender_id = m.sender_id
and m2.recipient_id = m.recipient_id
and m2.deleted_by_sender = 0
and m2.deleted_by_recipient = 0);
(and that assumes that (sender_id, recipient_id, created) is a unique key).

Categories