problem with mysql query - php

i have a table called users
this what the table look like
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL,
`password` varchar(60) NOT NULL,
`email` varchar(60) NOT NULL,
PRIMARY KEY (`id`)
)
and finally i have a table called friends,
this what the table look like
CREATE TABLE `friends` (
`friendship_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id1` bigint(20) unsigned NOT NULL,
`user_id2` bigint(20) unsigned NOT NULL,
`time_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`friendship_id`),
KEY `user_id1` (`user_id1`),
KEY `user_id2` (`user_id2`),
CONSTRAINT `friends_ibfk_1` FOREIGN KEY (`user_id1`) REFERENCES `users` (`id`),
CONSTRAINT `friends_ibfk_2` FOREIGN KEY (`user_id2`) REFERENCES `users` (`id`)
)
so basically if userA is following userB , then a row will be added to the friends table, with the attribute user_id1 is userA and user_id2 is userB.
im trying to write a mysql query for a searchbox. the user will enter a string and the query will crawl a list of users that include that string but the people that the user is following need to be displayed first.
so if we have 3 users
jack
jason
john
if the user Chris (who's following jason) enters in the searchbox the string 'ja', the query will crawl the list of users with the following order jason,jack. since jason is followed by chris.
from my understanding , i think it might a group by problem, i tried different queries but i couldnt get the needed results
do you guys have any idea ?
thanks a lot

You have to do a trick for sorting, so friendships get a 0 and non-friendships get a 1 in a temporary field and then we sort ascending for this field and as second we sort by username
SELECT x.username
FROM users x LEFT JOIN friends y ON x.id=y.user_id2 AND y.user_id1=$LOGGED_IN_USER
WHERE LOWER(x.username) LIKE 'ja%'
ORDER BY CASE WHEN y.user_id2 IS NULL THEN 1 ELSE 0 END,x.username
#thanks to scwagner for pointing me to extend JOIN-clause

Related

Why won't my foreign key create in MySQL?

I've tried many different ways to create table with a foreign key and trying to insert into phpMyAdmin. However, it just not working as I was expected.
Here are what I've so far:
CREATE TABLE user (
user_id BIGINT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_name VARCHAR(50) NOT NULL,
user_password VARCHAR(50) NOT NULL);
This works perfectly fine. However, if I try to add a table with a foreign key thus, it refuses to create:
CREATE TABLE article (
article_id INT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
article_title VARCHAR(100) NOT NULL,
article_content VARCHAR(1000) NOT NULL,
user_id INT(10) NOT NULL,
FOREIGN KEY (user_id) REFERENCES user (user_id));
This would not work as expected and would not add the table to the MySQL database. I get this error:
Cannot add foreign key constraint
How can I fix it?
We discovered in the comments that if a primary key is defined thus:
user_id BIGINT(10) UNSIGNED
then a foreign key like this will not work, since it needs to match on signedness (and I think type too):
user_id INT(10) NOT NULL
This works fine:
user_id BIGINT(10) UNSIGNED NOT NULL
Here's a Fiddle to demonstrate it working.

Sql Insert into with duplicate key

Ok so, im still a beginner in databases. i have this code
$sql="INSERT INTO complaints_members(password, complaint) VALUES ('$mypassword','$submit') ON DUPLICATE KEY UPDATE complaint='$submit' ; ";
This simply updates my complaint in the existing entry. How can i insert a new entry with the same key, instead of updating the old one?
Im thinking of it like this.
1st entry is like
Password : 123
Complaint : abc
2nd would be like
Password : 123
Complaint : def
Im not very familiar with the terms of SQL, so i'm sorry in advance, and thanks for your time.
EDIT: This is how the tables are
You can't have duplicate primary keys in a database. This is intentional.
Instead, consider re-designing your database so that each complaint has a unique ID (AKA a Primary Key). You should set it as something like complaint_id or simply id, and make it a PK (Primary Key) and AI (Auto-Increment). That way, when you do inserts you won't have to worry about updating the same row.
One option is to make password and complaint a composite primary key
For future reference when someone asks for your table structure its better to post the text from SHOW CREATE TABLE table_name instead of an image from a visual editor.
That said the problem is that your primary key is the password field. You need to add primary keys to both tabled than can be uniquely identified and then you need to link them.
Your table structure should be more like this:
CREATE TABLE `register` (
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`number` INTEGER(255),
`address` varchar(255),
PRIMARY KEY (`id`),
-- I assume that email and username should always be unique here
UNIQUE KEY (`email`)
UNIQUE KEY (`username`)
);
CREATE TABLE `complaints_members`
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`complaint` VARCHAR(255),
`password` varchar(255),
`member_id` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
KEY (`member_id`),
CONSTRAINT `complaints_members_register` FOREIGN KEY (`member_id`) REFERENCES `register` (`id`) ON DELETE CASCADE
);
So now to create a new member complaint your SQL would look like
INSERT INTO complaints_members(member_id, password, complaint) VALUES (?, ?, ?)
And to get all complaints for a member:
SELECT c.*
FROM compalaints_members c
WHERE c.member_id = ?

how to get users information stored in several tables and show in his profile, is it posible with single query?

i have developed an online auction system in which users can sale or buy goods, my problem is with retrieving auctions relative information that are in two separate tables one contains information such as (auction_id,owner,title,description,base_price,..) and the other contains information about requests for each auction: (bid_id,auction_id,bidder,price,date), each user may post several auctions or not, i want to show the highest price and the bidder(some one who gives such price) for that price and number of requests additional to information stored in auction table for each auction
but when i join to table, if there is no request for auction so the result will be zero and you will see the message: there is no information to show but the user has just posted a new auction, what should i do?! should i check if there is a request for each auction and if yes then get these information?! dosent in code duplication? in this way i should connect to db twice in a single request for profile page
here is my tables and current query:
create table `auction`(
`auction_id` INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
`owner` VARCHAR(32) NOT NULL,
`group_id` TINYINT UNSIGNED NOT NULL ,
`title` VARCHAR(100) NOT NULL,
`sale_type` VARCHAR(1) NOT NULL,
`base_price` INT NOT NULL,
`min_increase` INT NULL,
`photo` VARCHAR(200) NULL,
`description` VARCHAR(500) NOT NULL,
`start_date` DATETIME NOT NULL,
`termination_date` DATETIME NULL,
`sold` VARCHAR(1) NOT NULL DEFAULT 0,
`purchaser` VARCHAR(32) NULL,
`deleted` VARCHAR(1) NOT NULL DEFAULT 0,
FOREIGN KEY(owner) REFERENCES users(user_name) on delete cascade on update cascade,
FOREIGN KEY(purchaser) REFERENCES users(user_name) on delete cascade on update cascade,
FOREIGN KEY(group_id) REFERENCES commodity_groups(group_id) on delete cascade on update cascade)
ENGINE=InnoDB default charset=utf8;
create table `bid`(
`bid_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`auction_id` INT UNSIGNED NOT NULL,
`bidder` VARCHAR(32) NOT NULL,
`price` INT NOT NULL,
`date` DATETIME NOT NULL,
`deleted` VARCHAR(1) NOT NULL DEFAULT 0,
FOREIGN KEY(auction_id) REFERENCES auction(auction_id) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY(bidder) REFERENCES users(user_name) ON DELETE CASCADE ON UPDATE CASCADE)
ENGINE=InnoDB default charset=utf8;
and here is my query i use prepared statements:
SELECT `auction`.`auction_id` , `title` , `base_price` , `min_increase` , `photo` , `description` , `start_date` , `termination_date` , `max_bidder` , `bids_count` , `max_bid`
FROM `auction` , (
SELECT `bid`.`auction_id` , `bidder` AS max_bidder, `bids_count` , `max_bid`
FROM `bid` , (
SELECT `auction_id` , count( bid_id ) AS bids_count, max( price ) AS max_bid
FROM `bid`
WHERE `auction_id`
IN (
SELECT `auction_id`
FROM `auction`
WHERE `owner` = ?
)
GROUP BY (
auction_id
)
) AS temp
WHERE `bid`.`auction_id` = `temp`.`auction_id`
AND `price` = `max_bid`
) AS temp2
WHERE `auction`.`auction_id` = `temp2`.`auction_id`
it is clear that if there is no request for auction, the result will be zero and no auction will be shown to user in his profile, however he or she has just post a new auction, i will thank if any body could help me
What you have is more of a database design problem and a future scalability problem than an actual problem. You know you can make two requests if you want to.
If you care about scaling things up, you're going to have to think very carefully about what user information you want to replicate across multiple servers, and how you're going to synchronize that. The basic answer is: Yes, you use joins to include the user information you want. But a more complicated answer is that you might want to create mini tables with just a little bit of user information (duplicated and synchronized) that you can join very quickly, which no user would ever write to -- in other words they are written only by the master table either through a slave setup or with some cron job.
A lot depends on how large you expect your site to be and how many people might be writing to the users table. It's assumed that many people will be writing to the auction table, so ideally you don't want ANY foreign key dependencies on that table or you will get deadlocks. It should be an ISAM or Federated table, probably.

Different user roles for logging in with PHP and Mysql

I have a project coming up for doing Admin functions so my question is this. I will try and be clear as possible.
I will have one SUPER-USER who updates all information for other regular-users/people(being our clients).
The clients/regular-users when they log in will only see their info and download files uploaded by SUPER-USER and not see for regular-users.
So if you are Client:#01 you will see the dashboard (welcome page) and your info. Can anyone suggest possible database designs for this.
How to use left/right sql-joins between the user and files table?
UPDATE
I have a users table as well as a company table that the user belongs to. So essentially I want something like this::
$sql = select everything in the users table where the username and pass = to the given form, then left or right join that username to the company that he belong to.
Then they will see their information. if logged in successfully. Because user #01 belongs to company #03 /#01 etc...
USER TABLE looks so
`id` int(11) NOT NULL AUTO_INCREMENT,
`fname` varchar(50) NOT NULL,
'lname` varchar(100) NOT NULL,
`username` varchar(50) ,
`password` varchar(100) ,
`company` varchar(50) // the company name that ther user belongs to
PRIMARY KEY (`id`)
COMPANY table
'id' int(11) not null auto_increment,
'user_id' int(11) //This is to tie the users to this table
'description' varchar(text),
'filename' varchar(25) not null,
'mimetype' varchar (25) not null
PRIMARY KEY ('id')
Well, it depends on how simple or complex you want to go. with something like this I usually will keep it relatively simple and have a main user database (for all users) example:
CREATE TABLE IF NOT EXISTS `user` (
`user_id` int(255) NOT NULL AUTO_INCREMENT,
`user_name` varchar(50) NOT NULL,
`user_pass` varchar(100) NOT NULL,
`user_permissions` tinyint(1) NOT NULL DEFAULT '0',
`active` tinyint(1) NOT NULL DEFAULT '1',
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MYISAM;
Then I would have possible a second table of permissions depending on how many permissions I was going to have. If all you are going to have is users and super users then you could probably just assign users a value of 0 and then super user a value of 1.
Then in your PHP script it would treat the users different based on their "user_permissions" value.
Now if you are intending to have lots of different levels of permissions then I would definitely create at least one more table to define permissions example:
CREATE TABLE IF NOT EXISTS `permission` (
`permission_id` int(255) NOT NULL AUTO_INCREMENT,
`permission_name` varchar(100) NOT NULL,
`permission_value` int(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MYISAM;
Then in the permissions table you could assign all sorts of different permissions... read, write, publish, admin, regular user, super user etc.
This is just a very simple starting point. hope that helps.

MySQL table column description help needed

CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(50) NOT NULL,
`status` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
)
Please explain me what is doing UNIQUE KEY 'username' (username') statement in the example above and why ('username') is written once again?
The UNIQUE_KEY line is creating a unique index called 'username' on the column 'username'. A unique index allows only a single record to have a specific value. This is useful on rows like usernames because it prevents two users from being created with the same username.
However, I think you would get an error if you ran this because you have not defined a column called username.
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(50) NOT NULL,
`status` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
)
This is simply the format MySQL's CREATE TABLE syntax expects. If you look at the syntax in detail, you'll see...
UNIQUE [INDEX|KEY]
[index_name] [index_type] (index_col_name,...)
[index_option] ...
In other words, you're using an index_name of "username" which uses the "username" field/column. This might seem odd, but if you were using a compound key, you'd might have a definition something like...
UNIQUE KEY duplicate_lock (user_email, user_name)
...so you'd have different index name and column portions of the definition.

Categories