I have three tables "user" , "bidding" and "item".
I need to find the query in order to get the completed item auctions for a buyer. The way how to find this in my database is the following, item.received=1 AND u.userid=X (this X will be filled in from my PHP which gives the userID of the highest bid). (note that received=1 implies that the deadline is over so this check is not necessary anymore).
Short explanation of the system: it is an auction website, where a user places bids on items and on the users personal account page I want to show the amount of auctions which he bought (and are processed, thus completed).
The 3 tables look like this:
CREATE TABLE user (
userid INT NOT NULL AUTO_INCREMENT,
username CHAR(30) NOT NULL UNIQUE,
password CHAR(32) NOT NULL,
firstname CHAR(30) NOT NULL,
lastname CHAR(30) NOT NULL,
gender CHAR(1) NOT NULL,
email CHAR(50) NOT NULL UNIQUE,
birthdate DATE NOT NULL,
addressid INT NOT NULL,
picture CHAR(50),
lastlogin TIMESTAMP NOT NULL,
role CHAR(30),
paymentid INT NOT NULL,
PRIMARY KEY (userid),
FOREIGN KEY (addressid)
REFERENCES address(addressid),
FOREIGN KEY (paymentid)
REFERENCES payment(paymentid)
);
CREATE TABLE item (
itemid INT NOT NULL AUTO_INCREMENT,
name CHAR(40) NOT NULL,
description CHAR(255) NOT NULL,
originalpurchasedate DATE,
deadline TIMESTAMP NOT NULL,
minprice DOUBLE,
received BOOLEAN NOT NULL,
dateadded TIMESTAMP NOT NULL,
openbidding BOOLEAN NOT NULL,
categoryid INT NOT NULL,
ownerid INT NOT NULL,
PRIMARY KEY (itemid),
FOREIGN KEY (categoryid)
REFERENCES category(categoryid),
FOREIGN KEY (ownerid)
REFERENCES user(userid)
);
CREATE TABLE bidding (
userid INT NOT NULL,
itemid INT NOT NULL,
amount DOUBLE,
bidtime TIMESTAMP NOT NULL,
FOREIGN KEY (userid)
REFERENCES user(userid),
FOREIGN KEY (itemid)
REFERENCES item(itemid)
);
The malfunctioning solution I have already is: the result is 3 rows and results being: 3 , 1 , 5. The solution I expect to get only has to be 1 row, containing the number of distinct items.
SELECT DISTINCT COUNT(u.userid) FROM `item` i
INNER JOIN `bidding` b ON i.itemid = b.itemid
INNER JOIN `user` u ON b.userid = u.userid
WHERE i.received=1 AND u.userid=2
GROUP BY i.itemid
You need to change your query to group on userid instead of item id, and count different items instead of different users.
SELECT DISTINCT COUNT(i.itemid) FROM `item` i
INNER JOIN `bidding` b ON i.itemid = b.itemid
INNER JOIN `user` u ON b.userid = u.userid
WHERE i.received=1 AND u.userid=2
GROUP BY u.userid
Related
How can I combine these queries into a single query with where clause from another parent table? Please consider my SQL code and suggest a better method to work with
//look my code
CREATE TABLE IF NOT EXISTS first (
fid int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
p_name varchar(60) NOT NULL
);
CREATE TABLE IF NOT EXISTS second (
sed int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
firstname varchar(20) NOT NULL,
fid int(11) NOT NULL,
FOREIGN KEY (fid) REFERENCES first(fid)
);
CREATE TABLE IF NOT EXISTS third (
thid int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
start_date date NOT NULL,
end_date date NOT NULL,
sed int(11) NOT NULL,
FOREIGN KEY (sed) REFERENCES second(sed),
fid int(11) NOT NULL,
FOREIGN KEY (fid) REFERENCES first(fid)
);
CREATE TABLE IF NOT EXISTS fourth (
fid int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
start_date date NOT NULL,
end_date date NOT NULL,
sed int(11) NOT NULL,
FOREIGN KEY (sed) REFERENCES second(sed),
fid int(11) NOT NULL,
FOREIGN KEY (fid) REFERENCES first(fid)
);
CREATE TABLE IF NOT EXISTS fifth (
fiid int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
start_date date NOT NULL,
end_date date NOT NULL,
sed int(11) NOT NULL,
FOREIGN KEY (sed) REFERENCES second(sed),
fid int(11) NOT NULL,
FOREIGN KEY (fid) REFERENCES first(fid)
);
CREATE TABLE IF NOT EXISTS sixth (
sid int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
start_date date NOT NULL,
end_date date NOT NULL,
sed int(11) NOT NULL,
FOREIGN KEY (sed) REFERENCES second(sed),
fid int(11) NOT NULL,
FOREIGN KEY (fid) REFERENCES first(fid)
);
//As you can see above, I want to create a single query to query all data at the samee time i.e
//All table from third table depend on first and second table, but the second table have column firstname and the first table has the p_name column
//I want
SELECT second.*, third.* FROM second INNER JOIN third ON third.sed = second.sed
SELECT second.*, fourth.* FROM second INNER JOIN fourth ON fourth.sed = second.sed
SELECT second.*, fifth.* FROM second INNER JOIN fifth ON fifth.sed = second.sed
SELECT second.*, sixth.* FROM second INNER JOIN sixth ON sixth.sed = second.sed
....WHERE fid = 1;
I want to combine these queries into a single query ie, $newqueries = '.....';
The concept
The second table is used to carry all details, ie student details, but the third to sixth tables are tables with few different details but they took all other details from the second table, ie a student can be a chairman, secretary and vice secretary but not all students so that I classified them in third to sixth table. The first table used to keep few info about i.e classes so I want to differentiate chairman etc base on class tables but all of them are students
In short
A chairman, secretary and vice secretary are students but not all students have these role in a class but we have more than one classes, how to differentiate these leaders based on class
in a single query
You can use left join
SELECT second.*, third.*,fourth.*,fifth.*,sixth.* FROM second
LEFT JOIN third ON third.sed = second.sed
LEFT JOIN fourth ON fourth.sed = second.sed
LEFT JOIN fifth ON fifth.sed = second.sed
LEFT JOIN sixth ON sixth.sed = second.sed
WHERE second.fid = 1;
I assume that if student is chairman then there will be an entry of that student in third table. Above query will return null if the student is normal student. You can use CASE Statement if you want role as well. For example,
CASE WHEN third.startdate IS NULL THEN '' ELSE 'Chairman' END
I have two tables employees and departments.
Departments:
create table dept (
id INT NOT NULL AUTO_INCREMENT,
dept_name VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
);
Employees:
create table department_master (
id INT NOT NULL AUTO_INCREMENT,
dept_id INT NOT NULL,
emp_name VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
);
I want to prevent departments being deleted from the UI if they are assigned to one of the employees in employee table. Left join is giving me duplicate values.
How do I see if the departments are being used in the employees table.
If you want to prevent a department from being deleted, you can simply add a foreign constraint to the table department_master for dept_id column.
create table department_master (
id INT NOT NULL AUTO_INCREMENT,
dept_id INT NOT NULL,
emp_name VARCHAR(100) NOT NULL,
PRIMARY KEY (id),
constraint con_dm foreign key dept_id references dept( id )
);
It's default behavior is ON DELETE RESTRICT which means that if there is atleast one row present in the department_master for a given dept_id, it can't be deleted from dept table.
If you want to fetch, the department that don't have any employee record, you can use NOT EXISTS:
select *
from dept d
where not exists (
select 1
from department_master m
where d.id = m.dept_id
);
I believe you want a count of the number of employees grouped by the department, like so:
SELECT count(*) as employees, d.dept_name FROM dept AS d LEFT JOIN department_master AS e ON e.dept_id = d.id group by e.dept_id
I have a list of users that can enroll into courses and pay for them.
And I want to do a list of those users, and the courses that they are enrolled in and show there how much they've paid for each course already.
These are my tables:
CREATE TABLE usuarios(
userID int unsigned not null auto_increment primary key,
userEmail char(50) null,
userDNI int(10) null
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE rolesUsuarios (
rolesUsuariosID int unsigned not null auto_increment primary key,
userID int not null,
nombreRol char(50) not null
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE cursos (
cursoID int unsigned not null auto_increment primary key,
nombreCurso char(100) not null,
cursoPrecio int(10) null
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE cursosUsuarios (
cursosUsuariosID int unsigned not null auto_increment primary key,
userID int not null,
cursoID int not null
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE pagos (
pagoID int unsigned not null auto_increment primary key,
userID int not null,
pagoMonto int null
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE pagosVerificados (
pagosVerificadosID int unsigned not null auto_increment primary key,
userID int not null,
pagoID int not null,
cursoID int not null
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
And this is the query that I'm using:
SELECT usuarios.userID AS useridd, usuarios.userEmail, usuarios.userApellido, rolesUsuarios.userID, rolesUsuarios.nombreRol,
cursos.cursoID, cursos.nombreCurso,
cursosUsuarios.cursoID, cursosUsuarios.userID,
GROUP_CONCAT(DISTINCT rolesUsuarios.nombreRol SEPARATOR '||') AS 'roles',
GROUP_CONCAT(DISTINCT cursos.cursoID,' - ',cursos.nombreCurso SEPARATOR '||') AS 'cursos',
GROUP_CONCAT(DISTINCT '$ ',pagos.pagoMonto,' course ID ',pagosVerificados.cursoID,'payment ID',pagos.pagoID ORDER BY pagos.pagoID SEPARATOR '||') AS 'pagos'
FROM usuarios LEFT JOIN rolesUsuarios ON usuarios.userID = rolesUsuarios.userID
LEFT JOIN cursosUsuarios ON usuarios.userID = cursosUsuarios.userID
LEFT JOIN cursos ON cursosUsuarios.cursoID = cursos.cursoID
LEFT JOIN roles ON rolesUsuarios.nombreRol = roles.nombreRol
LEFT JOIN pagosVerificados
ON rolesUsuarios.userID = pagosVerificados.userID
LEFT JOIN pagos
ON pagosVerificados.userID = pagos.userID
AND pagosVerificados.pagoID = pagos.pagoID
GROUP BY useridd
This is the result I get: A list of all payments in the same list, and I want to separate them according to each course.
The ultimate goal is to be able to compare the price of each course with the sum of all payments done for each course and know if there's any debt in any course.
How may I do that? Could I do that using PHP directly and that query, or should I modify the query?
Again I don't speak whatever language this is, but I would start with this and this join to others tables as needed.
select A.userID, A.cursoID, B.cursoPrecio, IFNULL(sums.totalpaid, 0) `totalpaid`, (B.cursoPrecio - IFNULL(sums.totalpaid, 0)) `amount left`
from `cursosusuarios` A
inner join `cursos` B on (A.cursoID = B.cursoID)
left outer join (
select A.userID, A.cursoID, sum(B.pagoMonto) `totalpaid`
FROM `pagosverificados` A
inner join `pagos` B on (A.userID = B.userID and A.pagoID = B.pagoID)
group by A.userID, A.cursoID ) sums on (A.userID = sums.userID AND A.cursoID = sums.cursoID)
I'm executing the following statement:
SELECT DISTINCT
r.Recipe_Name
FROM
USER u
INNER JOIN
UserIngredient ui
ON
u.User_ID = ui.User_ID
INNER JOIN
RecipeIngredient ri
ON
ui.Ingredient_ID = ri.Ingredient_ID
INNER JOIN
Ingredient i
ON
ri.Ingredient_ID = i.Ingredient_ID
INNER JOIN
Recipe r
ON
ri.Recipe_ID = r.Recipe_ID
WHERE
u.User_Session = SessionID
and get every recipe that I have at least one ingredient for and not just the recipes that I have ALL ingredients for. My table-layout is the following:
CREATE TABLE User
(
User_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
User_Pass TEXT NOT NULL,
User_Name TEXT NOT NULL,
User_Surname TEXT NOT NULL,
User_EMail VARCHAR(255) UNIQUE,
User_Session VARCHAR(50) UNIQUE,
User_Admin BOOLEAN,
User_Newsletter BOOLEAN
);
CREATE TABLE Recipe
(
Recipe_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Recipe_Name VARCHAR(255) UNIQUE NOT NULL,
Recipe_Clicks INT,
Recipe_Description TEXT,
Recipe_Image VARCHAR(255) DEFAULT 'https://placehold.it/400x500'
);
CREATE TABLE Ingredient
(
Ingredient_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Ingredient_Name VARCHAR(255) UNIQUE,
Ingredient_Description TEXT
);
CREATE TABLE RecipeIngredient
(
RecipeIngredient_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
RecipeIngredient_Amount DECIMAL(8,2) NOT NULL,
MeasuringUnit_ID INT NOT NULL,
Recipe_ID INT NOT NULL,
Ingredient_ID INT NOT NULL,
FOREIGN KEY (MeasuringUnit_ID) REFERENCES MeasuringUnit(MeasuringUnit_ID),
FOREIGN KEY (Recipe_ID) REFERENCES Recipe(Recipe_ID),
FOREIGN KEY (Ingredient_ID) REFERENCES Ingredient(Ingredient_ID)
);
CREATE TABLE UserIngredient
(
UserIngredient_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Ingredient_ID INT NOT NULL,
User_ID INT NOT NULL,
FOREIGN KEY(Ingredient_ID) REFERENCES Ingredient(Ingredient_ID),
FOREIGN KEY(User_ID) REFERENCES User(User_ID)
);
The result I get:
I get every recipe that I have one ingredient
The result I want:
All recipes that I have ALL ingredients.
Here is my SQL file
Try this:
SELECT DISTINCT r.Recipe_Name
FROM Recipe r
CROSS JOIN User u
WHERE
(SELECT COUNT(*)
FROM RecipeIngredients ri
LEFT OUTER JOIN UserIngredient ui
ON ri.Recipe_ID = ui.Recipe_ID
AND ri.Ingredient_ID = ui.Ingredient_ID
AND ui.User_ID = u.User_ID
WHERE ui.UserIngredient_ID IS NULL) = 0
I have a forum split into multiple tables: categories, topics and threads.
CREATE TABLE forum_categories (
cat_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
role_id INTEGER UNSIGNED NOT NULL DEFAULT 0,
cat_name VARCHAR(50) NOT NULL,
PRIMARY KEY(cat_id),
FOREIGN KEY (role_id)
REFERENCES roles(role_id)
);
CREATE TABLE forum_topics (
topic_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
cat_id INTEGER UNSIGNED NOT NULL,
topic_name VARCHAR(50) NOT NULL,
topic_desc VARCHAR(100) NOT NULL,
PRIMARY KEY(topic_id),
FOREIGN KEY (cat_id)
REFERENCES forum_categories(cat_id)
);
CREATE TABLE forum_threads (
thread_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INTEGER UNSIGNED NOT NULL DEFAULT 0,
topic_id INTEGER UNSIGNED NOT NULL,
user_id INTEGER UNSIGNED NOT NULL,
title VARCHAR(100) NOT NULL,
body TEXT NOT NULL,
create_date DATETIME NOT NULL,
PRIMARY KEY (thread_id),
FOREIGN KEY (parent_id)
REFERENCES forum_threads(thread_id),
FOREIGN KEY (topic_id)
REFERENCES forum_topics(topic_id),
FOREIGN KEY (user_id)
REFERENCES users(user_id)
);
The category table has a field named role_id, which if set to any value other than 0 means that only users with that role are allowed to view or interact with the topics in that category.
The problem I'm facing is when attempting to pull a specific users recent activity for everyone to see. I want to COUNT(*) on the threads table containing the requested user_id, but I need to exclude threads having a topic_id associated with a restricted category unless the user requesting the information has permission.
If viewing a specific thread, I would simply extract the topic_id and check like this:
// validate topic id and check for permission
$forum = new Forum();
$valid_topics = $forum->getTopics();
if (!array_key_exists($topic_id, $valid_topics)) {
// invalid topic id
}
$valid_categories = $forum->getCategories();
$role_id = $valid_categories[$valid_topics[$topic_id]['cat_id']]['role_id'];
if ($role_id == 0 || array_key_exists($role_id, $session_user_roles)) {
// user has permission
}
Now I'm trying to convert my PHP logic into SQL. Here is a pseudo-code example of what I'm after:
SELECT COUNT(*),
(SELECT role_id,
(SELECT cat_id
FROM forum_topics AS t2
WHERE topic_id = t1.topic_id) AS cat_id
FROM forum_categories
WHERE cat_id = t2.cat_id) AS role_id
FROM forum_threads AS t1
WHERE user_id = $user_id AND (role_id != 0 OR FIND_IN_SET(role_id, $session_user_roles) > 0)
Any help, please?
Try this way
SELECT count(*)
FROM forum_threads thr
JOIN forum_topics top ON thr.topic_id = top.topis_id
JOIN forum_categories fc ON top.cat_id = fc.cat_id
WHERE thr.user_id = $user_id
AND fc.role_id IN ( 0, 24, 55, 888, .... list of user roles ... )
In the list of user roles (last condition) always put 0 as a first number, then the rest of his roles.