MySql searching for shared values across different rows - mysql

So I was looking for a possible solution to my problem but could not find it anywhere. I have a log table that logs users' visits (campaign name, IPs, useragent string, hostname etc etc). What I'm trying to get is a list of shared IPs that were seen across the campaigns I define.
so, here is my table for ex:
Log
-------------------------------------------------------------------
id ip campaignName UserName
-------------------------------------------------------------------
1 173.45.87.2 UK-Test John
2 12.45.76.53 Go-4 John
3 173.45.87.2 Robo-s John
4 67.55.33.77 Wrangles John
5 3.25.233.53 Stan-Die John
6 173.45.87.2 StartMa John
7 123.45.67.23 Fresh.Goal John
8 54.23.57.86 Ert56 John
9 173.45.87.2 Yuoit John
Desired output should be:
173.45.87.2
As this IP only appears in all UserName (John) campaigns.
forgot to mention that I know the UserName and all his campaigns, it's just the shared IPs across campaigns that I'm looking for.
Thanks for all helpers

SELECT ip
FROM Log
WHERE UserName = 'John'
GROUP BY ip
HAVING COUNT(*) > 1

Related

database table structure to store user location

I have a requirement to store user's proper location & send them newsletters as per them, I would like to understand the best way to store them as I have been finding it challenging to retrieve it after storing.
First of all, the address that needs to be stored is like:-
Country1-City1-SocietyName1-AnyMoreSmallLocation1-...so on.
So, now what I have done so far...
Table 1...
PID Place Parent
1 Country1 0
2 Country2 0
3 City1 1
4 City2 1
5 City3 2
6 Society1 3
n so on
Then
User table where I am keeping location with UID
UID Name PID
1. John 6
2. Sam 7
But at the get call of user location it needs to be like this...society name, city, country. which seems not good as per current design..please suggest.
If each user has only one adress, consider having only one table :
UID Name Country City etc.
But if there is multiple adresses per user, 2 tables (User and Adress):
UID Name
AdresseID UID Country City etc.

Merging and converting rows to columns

I have a list of data that happens to have been set up like this:
entryID fieldID Value
100 1 John
100 2 Smith
100 3 USA
101 1 Jane
101 2 Doe
101 3 USA
The way it works is, when a "ticket" is created, it assigns an entryID for all the data in that ticket, but each field also has it's own fieldID. So first name is always a fieldID of 1, last name is 2, etc.
What I need to be able to do is create a view that will look like this:
First Name Last Name Country
John Smith USA
Jane Doe USA
I need to be able to do this in MySQL, and not SQL or excel, as some other similar problems have addressed.
I just found the answer to my own question, so I will post it here for future users.
This website explains how to do exactly what I was asking for: http://stratosprovatopoulos.com/web-development/mysql/pivot-a-table-in-mysql/

SQL Query Giving Unique Fields Per User With Count

I'm trying to figure out a query that counts the number of times a user has given a unique answer and returns the user, answer, and count of those answers. The table looks like this:
Table Likes
ID Username Choice
1 Bobby Cat
2 Tina Rabbit
3 Bobby Rabbit
4 Alex Goose
5 Bobby Cat
6 Alex Goose
7 Alex Dog
After running the query, I hope to get each user along with his choices and the count of each like so:
Result
Username Choice Count(Selection)
Bobby Rabbit 1
Bobby Cat 2
Tina Rabbit 1
Alex Goose 2
Alex Dog 1
The best I've come up with so far is:
SELECT Username, Choice, Count(Choice) FROM Likes GROUP BY Username
But this is not quite right.
You need to add Choice in Group by to count the number of times a user has given a unique answer. Without choice in Group by u will get the count of answers given by each user
SELECT Username,
Choice,
Count(Choice)
FROM Likes
GROUP BY Username,
choice
This query will be helpful.
SELECT Username, Choice, Count(Choice) AS CountSelection
FROM Likes
GROUP BY Username, Choice

Aggregating multiple groups in SQL

I have an application that needs to query a MySQL database and retrieve a list of users that may be sharing an IP address, and I am having some trouble turning my the concept of what I want to do with my query in my head into a functional query.
The situation is that I have a table which contains known ip information for users. Each time the user logs in, it creates a timestamped entry containing their user id and the ip address they logged into.
Initially, I used the following query to return rows representing IP addresses that were shared:
select ip, GROUP_CONCAT(DISTINCT account ORDER BY timestamp SEPARATOR ' ')
from known_ips
group by ip having count(1) > 1
However, many users have dynamic IP addresses so this list contains many duplicate entries (one for each IP address they share with others, obviously).
What I would like to do is have each row returned be a unique group of users that have shared any ip address with one another at any point.
For example, if Bob and Jane had shared IP address 192.168.0.1 and Bob and Fred had shared IP address 192.168.0.2, I would want the row to return 'Bob Fred Jane' (the program is taking the results of this query and doing some operations with it, and essentially needs a list of accounts on which to take action).
What I can't figure out on my own is how to do this aggregation (or whether it is even possible). I initially tried to have the original query as CTE (using with clause) and then trying to group on that, however I reached a stumbling block in that I couldn't figure out how to logically carry out the operation "compare string-delimited list of users in group 1 to see if any exist in group 2", and I figure doing that sort of string comparison is not what SQL is all about anyway (and I can do it in the program rather than the SQL besides).
Does anyone know of any technique whereby I can represent the logic of what I am trying to achieve here in MySQL? Or, should I accept the solution I already reached and then do the aggregation in the client application?
Edit:
In response to the request to a sample of data and output, here is a contrived example of the data:
Account IP Timestamp
Bob 192.168.0.1 2014-02-12 08:00
Bob 192.168.0.1 2014-02-12 09:30
Bob 192.168.0.2 2014-02-12 10:00
Mary 192.168.0.1 2014-03-12 07:00
Bob 192.168.0.2 2014-03-12 08:00
Jim 192.168.0.4 2014-03-12 08:30
Ted 192.168.0.2 2014-03-12 09:00
Jim 192.168.0.5 2014-04-12 08:30
Bob 192.168.0.3 2014-04-12 09:30
Andy 192.168.0.6 2014-04-12 10:30
Paul 192.168.0.6 2014-04-12 11:30
From this sample data, I would expect exactly two rows returned:
Bob Mary Ted
Andy Paul
I am ambivalent about the ordering of accounts in the list, despite my use of ORDER BY timestamp earlier.

SQL "shortcut" identifiers or a long string of joins?

QUESTION: Is it okay to have "shortcut" identifiers in a table so that I don't have to do a long string of joins to get the information I need?
To understand what I'm talking about, I'm going to have to lay ouf an example here that looks pretty complicated but I've simplified the problem quite a bit here, and it should be easily understood (I hope).
The basic setup: A "company" can be an "affiliate", a "client" or both. Each "company" can have multiple "contacts", some of which can be "users" with log in privileges.
`Company` table
----------------------------------------------
ID Company_Name Address
-- ----------------------- -----------------
1 Acme, Inc. 101 Sierra Vista
2 Spacely Space Sprockets East Mars Colony
3 Cogswell Cogs West Mars Colony
4 Stark Industries Los Angeles, CA
We have four companies in our database.
`Affiliates` table
---------------------
ID Company_ID Price Sales
-- ---------- ----- -----
1 1 50 456
2 4 50 222
3 1 75 14
Each company can have multiple affiliate id's so that they can represent the products at different pricing levels to different markets.
Two of our companies are affiliates (Acme, Inc. and Stark Industries), and Acme has two affiliate ID's
`Clients` table
--------------------------------------
ID Company_ID Referring_affiliate_id
-- ---------- ----------------------
1 2 1
2 3 1
3 4 3
Each company can only be a client once.
Three of our companies are clients (Spacely Space Sprockets, Cogswell Cogs, and Stark Industries, who is also an affiliate)
In all three cases, they were referred to us by Acme, Inc., using one of their two affiliate ID's
`Contacts` table
-----------------------------------------
ID Name Email
-- -------------- ---------------------
1 Wylie Coyote wcoyote#acme.com
2 Cosmo Spacely boss#spacely.com
3 H. G. Cogswell ceo#cogs.com
4 Tony Stark tony#stark.com
5 Homer Simpson simpson#burnscorp.com
Each company has at least one contact, but in this table, there is no indication of which company each contact works for, and there's also an extra contact (#5). We'll get to that in a moment.
Each of these contacts may or may not have a login account on the system.
`Contacts_type` table
--------------------------------------
contact_id company_id contact_type
---------- ---------- --------------
1 1 Administrative
2 2 Administrative
3 3 Administrative
4 4 Administrative
5 1 Technical
4 2 Technical
Associates a contact with one or more companies.
Each contact is associated with a company, and in addition, contact 5 (Homer Simpson) is a technical contact for Acme, Inc, and contact 4 (Tony Stark) is a both an administrative contact for company 4 (Stark Industries) and a technical contact for company 3 (Cogswell Cogs)
`Users` table
-------------------------------------------------------------------------------------
ID contact_id company_id client_id affiliate_id user_id password access_level
-- ---------- ---------- --------- ------------ -------- -------- ------------
1 1 1 1 1 wylie A03BA951 2
2 2 2 2 NULL cosmo BF16DA77 3
3 3 3 3 NULL cogswell 39F56ACD 3
4 4 4 4 2 ironman DFA9301A 2
The users table is essentially a list of contacts that are allowed to login to the system.
Zero or one user per contact; one contact per user.
Contact 1 (Wylie Coyote) works for company 1 (Acme) and is a customer (1) and also an affiliate (1)
Contact 2 (Cosmo Spacely) works for company 2 (Spacely Space Sprockets) and is a customer (2) but not an affiliate
etc...
NOW finally onto the problem, if there is one...
Do I have a circular reference via the client_id and affiliate_id columns in the Users table? Is this a bad thing? I'm having a hard time wrapping my head around this.
When someone logs in, it checks their credentials against the users table and uses users.contact_id, users.client_id, and users.affiliate_id to do a quick look up rather than having to join together a string of tables to find out the same information. But this causes duplication of data.
Without client_id in the users table, I would have to find the following information out like this:
affiliate_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `affiliates`.`company_id`
client_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `clients`.`company_id`
company_id: join `users`.`contact_id` to `contacts_types`.`company_id` to `company`.`company_id`
user's name: join `users`.`contact_id` to `contacts_types`.`contact_id` to `contacts`.`contact_id` > `name`
In each case, I wouldn't necessarily know if the user even has an entry in the affiliate table or the clients table, because they likely have an entry in only one of those tables and not both.
Is it better to do these kinds of joins and thread through multiple tables to get the information I want, or is it better to have a "shortcut" field to get me the information I want?
I have a feeling that over all, this is overly complicated in some way, but I don't see how.
I'm using MySQL.
it's better to do the joins. you should only be denormalizing your data when you have timed evidence of a slow response.
having said that, there are various ways to reduce the amount of typing:
use "as" to give shorter names to your fields
create views. these are "virtual tables" that already have your standard joins built-in, so that you don't have to repeat that stuff every time.
use "with" in sql. this lets you define something like a view within a single query.
it's possible mysql doesn't support all the above - you'll need to check the docs [update: ok, recent mysql seems to support views, but not "with". so you can add views to do the work of affiliate_id, client_id etc and treat them just like tables in your queries, but keeping the underlying data nicely organised.]