Subtracting output of 2 SQL queries - mysql

I'm a rookie and am trying to get the difference between two query outputs. Each query creates a list. Query A list > Query B list. Also, query B output is a subset of query A.
Query A:
SELECT first_name, last_name
FROM users
WHERE rating <> '6';
Query B:
SELECT DISTINCT first_name, last_name
FROM users
JOIN mp_positions
ON users.id=mp_positions.user_id
JOIN mps
ON mps.id=mp_positions.mp_id
WHERE mps.status_id = '5';
Any help would be appreciated.

I'm not entirely sure of the structure of your tables although you'll probably want to try something like this:
SELECT first_name, last_name
FROM users
WHERE rating <> '6'
AND users.id
NOT IN (SELECT DISTINCT first_name, last_name
FROM users
JOIN mp_positions
ON users.id=mp_positions.user_id
JOIN mps ON mps.id=mp_positions.mp_id
WHERE mps.status_id = '5'
);

Related

SQL query with most recent name and total count

I already have a table, "table_one", set up on phpMyAdmin that has the following columns:
USER_ID: A discord user ID (message.author.id)
USER_NAME: A discord username (message.author.name)
USER_NICKNAME: The user's display name on the server (message.author.display_name)
TIMESTAMP: A datetime timestamp when the message was entered (message.created_at)
MESSAGE CONTENT: A cleaned input keyword to successful completion of content, just for this example consider "apple" or "orange" as the two target keywords.
What I'd like as a result is a view or query that returns a table with the following:
The user's most recent display name (USER_NICKNAME), based off the most recent timestamp
The total number of times a user has entered a specific keyword. Such as confining the search to only include "apple" but not instances "orange"
My intention is that if a user entered a keyword 10 times, then changed their server nickname and entered the same keyword 10 more times, the result would show their most recent nickname and that they entered the keyword 20 times in total.
This is the closest I have gotten to my desired result so far. The query correctly groups instances where user has changed their nickname based on the static discord ID, but I would like it to retain this functionality while instead showing the most recent USER_NICKNAME instead of a USER_ID:
SELECT USER_ID, COUNT(USER_ID)
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID
I don't think there is an uncomplicated way to do this. In Postgres, I would use the SELECT DISTINCT ON to get the nickname, but in MySQL I believe you are limited to JOINing grouped queries.
I would combine two queries (or three, depending how you look at it).
First, to get the keyword count, use your original query:
SELECT USER_ID, COUNT(USER_ID) as apple_count
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID;
Second, to get the last nickname, group by USER_ID without subsetting rows and use the result as a subquery in a JOIN statement:
SELECT a.USER_ID, a.USER_NICKNAME AS last_nickname
FROM table_one a
INNER JOIN
(SELECT USER_ID, MAX(TIMESTAMP) AS max_ts
FROM table_one
GROUP BY USER_ID) b
ON a.USER_ID = b.USER_ID AND TIMESTAMP = max_ts
I would then JOIN these two, using a WITH statement to increase the clarity of what's going on:
WITH
nicknames AS
(SELECT a.USER_ID, a.USER_NICKNAME AS last_nickname
FROM table_one a
INNER JOIN
(SELECT USER_ID, MAX(TIMESTAMP) AS max_ts
FROM table_one
GROUP BY USER_ID) b
ON a.USER_ID = b.USER_ID AND TIMESTAMP = max_ts),
counts AS
(SELECT USER_ID, COUNT(USER_ID) AS apple_count
FROM table_one
WHERE MESSAGE_CONTENT = 'apple'
GROUP BY USER_ID)
SELECT nicknames.USER_ID, nicknames.last_nickname, counts.apple_count
FROM nicknames
INNER JOIN counts
ON nicknames.USER_ID = counts.USER_ID;

Inner join with where clause

This is my query
$searched = 'SELECT first_name, surname, team, id, time FROM users WHERE first_name LIKE "'.$firstname.'%" AND surname LIKE "'.$surname.'%"'
I need to do an inner join on a table of teams.
Structure is as follows.
id
teamname
slug
I need to get the teamname the join is in the teams.id and users.id.
I just can't seem to get the syntax right.
You need INNER JOIN. Also time is a keyword for MySQL and it's better to escape it. Fields id should be used with table name because they are ambiguous. Finally you are under SQL Injection threat.
SELECT users.first_name, users.surname, users.team, users.id AS users_id, `time`
FROM users
INNER JOIN teams
ON teams.id = users.id
WHERE users.first_name LIKE "'.$firstname.'%" AND users.surname LIKE "'.$surname.'%"
Also, is there any particular reason that the JOIN should be on teams.id and users.id. They are supposed to be different things.
Should you not have either team.id = users.teamid or team.userid = users.id in the where condition? Also in the select you have used "team". I guess it should be "teamname".
The SQL should probably be
SELECT
first_name,
surname,
teamname,
id,
time
FROM
users,
teams
WHERE
first_name LIKE "'.$firstname.'%"
AND surname LIKE "'.$surname.'%"'
AND users.teamid = teams.id

Add results of two mysql queries

How can I summarize results of two queries below?
select firstname, surname, COUNT(*) as Built
from orders
join users on orders.builder = users.id
where bStop > 1461496211 and bStop < 1461582649
group by users.id;
select firstname, surname, COUNT(*) as Built
from production_points
join users on production_points.rewarded = users.id
where Date(datetime) = '2016-04-25'
group by users.id
Same user can be in both tables, so i want to sum his results, don't want two separate lines i.e. first one showing 4 and second one 6. Just total 10
You can use Union.
If this is mysql you can see its syntax here: http://dev.mysql.com/doc/refman/5.7/en/union.html
It is similar in the other DB vendors.
Can you maybe get the result of each and assign them to different variables.
And sum up the variables.
After research as advised by you guys, here is the solution:
select uid, firstname, surname, Count(*) as Built from (
select users.id as uid, firstname, surname from orders join users on orders.builder = users.id where bStop > 1461542400 and bStop < 1461592622
union all
select users.id as uid, firstname, surname from production_points join users on production_points.rewarded = users.id where Date(datetime) ='2016-04-25'
) performance group by uid;

MySQL nested counts and returning values

I have searched high and low and can't seem to get a way to do what I want. I have a table with some customers, some products and their relationships.
I want to count the amount of returned rows from this part of the query
SELECT id
FROM customer
WHERE customer.name = 'SMITH'
OR customer.name = 'JONES'
I also want to return the ids that match SMITH and JONES (or other customer names chosen). I want to use the count of the returned rows as a variable (denoted as #var). I only want to return the products, id, and count that match my variable.
My questions are:
Is there a way that this can be done in a single SQL query?
Is there a way to return the count as well as the values?
I don't want to have to throw this into a PHP script or the like.
SELECT x.pId, p.productdesc, count(x.dId) as count
FROM
(
SELECT DISTINCT cId, pId
FROM Client
WHERE cId IN
(
SELECT id
FROM customer
WHERE customer.name = 'SMITH'
OR customer.name = 'JONES'
)
)x
JOIN Products p ON x.pId = p.id
GROUP BY x.pId
HAVING count = #var
Thanks,
M
This is sort of a 'literal' answer to what your asked, as you can use subqueries in the having clause. However, with more information (sample data and expected result) there may be a better way of doing what you want.
select x.pid, p.productdesc, count(x.pid) as count
from (select distinct cl.cid, cl.pid
from client cl
join customer cu
on cl.cid = cu.id
where cu.name in ('SMITH', 'JONES')) x
join products p
on x.pid = p.id
group by x.pid, p.productdesc
having count(x.pid) = (select count(*)
from customer
where name in ('SMITH', 'JONES'))

Stacked SQL Query error and complications

I just learned you can stack SQL queries instead of running 4 different ones and combining the data. So I'm read tutorials and stuff but still can't figure this certain one out.
SELECT ID,
(SELECT firstname
FROM user
WHERE ID = fundraiser.user_ID) AS firstname,
(SELECT lastname
FROM user
WHERE ID = fundraiser.user_ID) AS lastname,
(SELECT org_fund_id
FROM fundraiser
WHERE ID = fundraiser.ID) AS org_fund_ID,
(SELECT ref_ID
FROM fundraiser
WHERE ID = fundraiser.ID) AS ref_ID
FROM fundraiser
WHERE 1
ORDER BY org_fund_ID ASC
Here's the basic setup for the database/tables being called:
[fundraiser] - (ID, ref_ID, user_ID, org_fund_ID) and
[user] - (firstname, lastname)
Basically, I want to pull all of the fields from "fundraiser" from the database but get the corresponding "user.firstname" and "user.lastname" where "fundraiser.user_ID" = "user.ID".
So it would come out something like this as a row:
fundraiser.ID, fundraiser.user_ID, fundraiser.ref_ID, user.firstname, user.lastname
I've tried like 30 different ways of writing this query and all have failed. The error I get is "#1242 - Subquery returns more than 1 row".
Not sure how I can give you more information so you can visualize what I'm talking about, but I will provide whatever data I can.
Thanks in advance.
to select ALL columns:
SELECT *
FROM fundraiser f
INNER JOIN user u
ON u.ID = f.user_ID
ORDER BY f.ord_fund_id ASC;
to select needed columns:
SELECT
u.firstname,
u.lastname,
f.org_fund_id,
f.ref_ID
FROM fundraiser f
INNER JOIN user u ON u.ID = f.user_ID
ORDER BY f.ord_fund_id ASC;
this should be, what you need. See this Wikipedia page.