How to get users by last message in Laravel Eloquent - mysql

I'm currently developing a simple chat application with Laravel 8 and VueJS. I need to order users by their latest message and get the last message along with the user. Below are the tables I am using if anyone has an idea for this operation. If it's an Eloquent method, it would be better.
Users Table
create table users
(
id bigint unsigned auto_increment
primary key,
name varchar(255) not null,
email varchar(255) not null,
email_verified_at timestamp null,
password varchar(255) not null,
two_factor_secret text null,
two_factor_recovery_codes text null,
remember_token varchar(100) null,
status varchar(255) default 'online' not null,
last_seen timestamp null,
current_team_id bigint unsigned null,
profile_photo_path varchar(2048) null,
created_at timestamp null,
updated_at timestamp null,
constraint users_email_unique
unique (email)
)
collate = utf8mb4_unicode_ci;
Private Messages Table
create table private_messages
(
id bigint unsigned auto_increment
primary key,
sender_id bigint unsigned not null,
receiver_id bigint unsigned not null,
message varchar(1000) not null,
delete_type varchar(15) null,
created_at timestamp null,
updated_at timestamp null,
deleted_at timestamp null,
constraint private_messages_receiver_id_foreign
foreign key (receiver_id) references users (id)
on delete cascade,
constraint private_messages_sender_id_foreign
foreign key (sender_id) references users (id)
on delete cascade
)
collate = utf8mb4_unicode_ci;

in user model create relation function
public function privateMessages()
{
return $this->hasMany(PrivateMessage::class)->orderBy('id','DESC');
}
then use
$users = User::with('privateMessages')->all();
in this result , messages sort by id desc.

Related

How can i improve GROUP BY statement performance?

I have a big query that i need to optimize.
select game_id,
count(user_id),
count(distinct user_id),
provider_id,
aggregator,
country,
sum(sum_bets),
sum(sum_wins),
currency,
any_value(date)
from (select transactions.game_id as game_id,
transactions.user_id as user_id,
games.provider_id as provider_id,
games.aggregator as aggregator,
users.country as country,
transactions.currency as currency,
IF(transactions.type_id IN (2, 16), transactions.amount, 0) as sum_bets,
IF(transactions.type_id IN (3, 18, 20), transactions.amount, 0) as sum_wins,
transactions.date_create as date
from `transactions`
inner join `games` on transactions.game_id = games.id
inner join `users` on transactions.user_id = users.id
where transactions.status_id = 1
and transactions.type_id in (2, 3, 16, 18, 20)
and transactions.game_id is not null
and users.country is not null
union all
select transactions_bonus.game_id as game_id,
transactions_bonus.user_id as user_id,
games.provider_id as provider_id,
games.aggregator as aggregator,
users.country as country,
transactions_bonus.currency as currency,
IF(transactions_bonus.type IN (5, 6), transactions_bonus.amount_bonus, 0) as sum_bets,
IF(transactions_bonus.type IN (4, 7, 10), transactions_bonus.amount_bonus, 0) as sum_wins,
transactions_bonus.date as date
from `transactions_bonus`
inner join `games` on transactions_bonus.game_id = games.id
inner join `users` on transactions_bonus.user_id = users.id
where transactions_bonus.status in (2, 3, 4, 5, 6)
and transactions_bonus.type in (4, 5, 6, 7, 10)
and transactions_bonus.game_id is not null
and users.country is not null) as popular_games
group by game_id, provider_id, aggregator, country, currency
Table transactions
-- auto-generated definition
create table transactions
(
id bigint unsigned auto_increment
primary key,
string_id varchar(36) null,
user_id bigint unsigned not null,
game_id smallint unsigned null,
bonus_id smallint unsigned null,
jackpot_id bigint unsigned null,
prize_id bigint unsigned null,
tournament_id bigint unsigned null,
amount int not null,
commission int null,
aggregator_amount int unsigned default '0' not null,
aggregator_currency varchar(16) collate utf8_bin null,
aggregator_fee int unsigned default '0' not null,
currency varchar(3) not null,
status_id tinyint unsigned not null,
balance int null,
gateway_method varchar(64) null,
account varchar(128) collate utf8_bin null comment 'Аккаунт в платежной системе (номер карты, телефон, кошелек)',
ip varchar(39) null,
comment varchar(128) null,
date_create datetime default CURRENT_TIMESTAMP not null,
date_complete datetime null,
date_cancel datetime null,
type_id tinyint unsigned not null,
manager_id int null,
event_id int null,
constraint transactions_ibfk_1
foreign key (user_id) references users (id)
on update cascade,
constraint transactions_ibfk_2
foreign key (game_id) references games (id)
on update cascade,
constraint transactions_ibfk_3
foreign key (jackpot_id) references jackpots (id)
on update cascade,
constraint transactions_ibfk_4
foreign key (tournament_id) references tournaments (id)
on update cascade,
constraint transactions_prize_id_foreign
foreign key (prize_id) references prizes (id)
on update cascade
)
engine = InnoDB;
create index date_create
on transactions (date_create);
create index game_id
on transactions (game_id);
create index jackpot_id
on transactions (jackpot_id);
create index string_id
on transactions (string_id);
create index tournament_id
on transactions (tournament_id);
create index type_id
on transactions (type_id);
create index user_id
on transactions (user_id);
Table transactions_bonus
-- auto-generated definition
create table transactions_bonus
(
id bigint unsigned auto_increment
primary key,
account tinyint unsigned default '1' not null comment 'Номер счета. 1 - бонусный счет казино, 2 - бонусный счет спорта',
type tinyint unsigned not null,
user_id bigint unsigned not null,
admin_id bigint unsigned null,
transaction_id bigint unsigned null,
bonus_id bigint unsigned null,
tournament_id bigint unsigned null,
prize_id bigint unsigned null,
game_id smallint unsigned null,
amount_bonus int not null,
amount_deposit int null,
currency varchar(3) not null,
wager float not null,
max_bet int unsigned null,
max_transfer int unsigned default '0' not null comment 'Максимальная сумма перевода с бонусного счета на основной',
balance int not null,
status tinyint unsigned not null,
comment text null,
date timestamp default CURRENT_TIMESTAMP not null,
date_cancel timestamp null,
date_wagering_complete timestamp null,
constraint transactions_bonus_ibfk_1
foreign key (admin_id) references users (id)
on update cascade,
constraint transactions_bonus_ibfk_3
foreign key (tournament_id) references tournaments (id)
on update cascade,
constraint transactions_bonus_ibfk_4
foreign key (user_id) references users (id)
on update cascade,
constraint transactions_bonus_ibfk_5
foreign key (game_id) references games (id)
on update cascade,
constraint transactions_bonus_ibfk_6
foreign key (prize_id) references prizes (id)
on update cascade,
constraint transactions_bonus_ibfk_7
foreign key (bonus_id) references bonuses (id)
on update cascade,
constraint transactions_bonus_ibfk_8
foreign key (transaction_id) references transactions (id)
on update cascade
)
engine = InnoDB;
create index account
on transactions_bonus (account);
create index admin_id
on transactions_bonus (admin_id);
create index bonus_id
on transactions_bonus (bonus_id);
create index game_id
on transactions_bonus (game_id);
create index status
on transactions_bonus (status);
create index tournament_id
on transactions_bonus (tournament_id);
create index transaction_id_2
on transactions_bonus (transaction_id);
create index type
on transactions_bonus (type);
create index user_id
on transactions_bonus (user_id);
Table games
-- auto-generated definition
create table games
(
id smallint unsigned auto_increment
primary key,
string_id varchar(96) collate utf8_bin not null,
provider_id tinyint unsigned not null,
aggregator tinyint unsigned not null,
name varchar(255) not null,
game_type tinyint unsigned not null,
source tinyint unsigned not null,
technology tinyint unsigned not null,
device_type tinyint unsigned not null,
status tinyint unsigned default '0' not null,
block_kyc tinyint unsigned default '0' not null comment 'Блокировка для не верифицированных пользователей',
block_jackpots tinyint unsigned default '0' not null comment 'Не участвует в джекпотах',
is_blocked_tournaments tinyint unsigned default '0' not null,
is_wagering tinyint default 0 null,
is_bonuses tinyint unsigned default '0' null,
is_jackpots tinyint unsigned default '0' not null,
freespins tinyint unsigned default '0' not null comment 'Участвует в фриспинах',
has_demo tinyint(1) default 0 not null,
multiplier decimal(8, 2) unsigned default 0.00 not null,
image varchar(128) null,
sorting int unsigned default '0' not null,
created_at timestamp default CURRENT_TIMESTAMP null,
updated_at timestamp null,
blocked smallint unsigned default '0' null,
constraint string_id
unique (string_id, aggregator),
constraint games_ibfk_1
foreign key (provider_id) references games_providers (id)
)
engine = InnoDB;
create index provider_id
on games (provider_id);
Table users
-- auto-generated definition
create table users
(
id bigint unsigned auto_increment
primary key,
name varchar(255) charset utf8 null,
surname varchar(255) null,
email varchar(255) null,
phone varchar(12) null,
password varchar(255) not null,
user_group tinyint(1) not null,
status tinyint(1) default 0 not null,
network varchar(32) null,
network_uid varchar(32) null,
login varchar(255) not null,
ip_registration varchar(39) not null,
ip_auth varchar(39) null,
country varchar(3) charset utf8 null,
country_already_changed tinyint unsigned default '0' not null comment 'Страну можно изменить только один раз',
birthday_already_changed tinyint unsigned default '0' not null comment 'Дату рождения можно установить один раз',
city varchar(255) null,
postcode varchar(15) null,
date_birth date null,
date_registration timestamp default CURRENT_TIMESTAMP not null,
date_auth timestamp null,
date_last_activity timestamp null,
comment varchar(265) null,
affiliate_id varchar(32) charset utf8 null,
affiliate_user_id varchar(255) null,
affiliate_company_id varchar(32) null,
affiliate_payload varchar(192) charset utf8 null,
affiliate_link_type tinyint unsigned default '0' not null comment 'Тип партнерской ссылки, по которой перешел юзер',
favorite_bets tinyint unsigned default '0' not null comment 'Любимые ставки игрока',
timezone varchar(64) charset utf8 null,
region varchar(255) null,
address varchar(265) null,
kyc_status tinyint unsigned default '1' not null,
role_id tinyint null,
sms_autentification tinyint unsigned default '0' not null,
remember_token varchar(100) null,
created_at timestamp default CURRENT_TIMESTAMP not null,
updated_at timestamp null,
kyc_expire date null,
sex varchar(1) charset utf8 default 'm' null,
login_attempt int default 0 not null,
language varchar(2) charset utf8 default 'en' not null,
session_uuid varchar(36) null,
session_token varchar(64) null,
avatar varchar(265) null,
referral_user_id bigint unsigned null,
level tinyint unsigned default '0' not null,
points int unsigned default '0' not null,
shop_points int unsigned default '0' not null,
last_points_used timestamp null,
max_withdrawal_amount int unsigned null,
promocode_error_attempts int unsigned default '0' null,
promocode_block_to datetime null,
bonus_blocked tinyint unsigned default '0' not null comment 'Заблокирован для участия в бонусах',
bonus_blocked_date timestamp null,
blocked tinyint unsigned default '0' not null comment 'Блокировка Sumsub',
service_status varchar(32) null comment 'Статус сервиса SumSub',
constraint login
unique (login),
constraint network
unique (network, network_uid),
constraint users_email_unique
unique (email),
constraint users_ibfk_1
foreign key (referral_user_id) references users (id)
on update cascade
)
engine = InnoDB
collate = utf8mb4_unicode_ci;
create index date_last_activity
on users (date_last_activity);
create index referral_user_id
on users (referral_user_id);
These two merged tables have combined 30 million rows, without GROUP BY statement, it executes within a 1.5-2 seconds. With GROUP BY, i can wait up to 5 minutes until it executes.
Obviously, i can execute script without GROUP BY, and then format and aggregate it in my code.
But so many records will breach the limit of my RAM, if i will save it in array or JSON.
Be aware that count(user_id) counts the number of rows that have user_id IS NOT NULL. It seems like it won't be NULL, so you may as well do COUNT(*).
In older versions ANY_VALUE(date) does not work but MIN(date) works.
There are lot of IN(...) lists; this makes it virtually impossible to fashion any useful INDEXes. Here are some that could help:
transactions: INDEX(status_id, type_id)
If it weren't for COUNT(DISTINCT user_id), I would recommend doing the SUMs in each subquery, then adding the subtotals.
What is the value of innodb_buffer_pool_size? How much RAM? How big are the tables (in GB)? If things can't be cached adequately, then I/O is the problem and I will suggest changing BIGINTs (8 bytes each) to more civilized datatypes.
"two merged tables have combined 30 million rows" -- Is it 30M before or after filtering (WHERE)?
Please provide EXPLAIN SELECT ...

Create two tables customer_data and order_data in SQL in a single execution via PHP

CREATE TABLE IF NOT EXISTS customers_data (
id int(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
INVOICE_ID varchar(50) NOT NULL,
_NAME varchar(255) NOT NULL,
MOBILE bigint(12) NOT NULL,
GSTIN varchar(20) NOT NULL,
_ADDRESS varchar(255) NOT NULL,
EMAIL varchar(255) NOT NULL,
_STATE varchar(50) NOT NULL,
MODE varchar(10) NOT NULL,
_DATE date NOT NULL DEFAULT current_timestamp(),
total_qty int(11) NOT NULL,
total_amount decimal(40,2) NOT NULL,
total_sc_gst decimal(30,2) NOT NULL,
Round_Off float(2,2) NOT NULL,
grand_total decimal(50,0) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
customer_data created sucessfully.
But there is an error in order_data regarding foreign key. Remember I want to create these two table in a same time.
CREATE TABLE IF NOT EXISTS order_data (
id int(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
cus_id int(20) NOT NULL,
ITEM varchar(255) NOT NULL,
HSN varchar(50) NOT NULL,
QTY int(15) NOT NULL,
RATE decimal(40,2) NOT NULL,
S_C_GST decimal(30,2) NOT NULL,
TOTAL decimal(50,2) NOT NULL,
_DATE timestamp NOT NULL DEFAULT current_timestamp(),
FOREIGN KEY(cus_id) REFERENCES customers_data(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
I got this error.
#1005 - Can't create table test. (errno: 150 "Foreign
key constraint is incorrectly formed")
I think you are using MySQL. You have not used Constraint with Foreign Key. Try the below query.
CREATE TABLE IF NOT EXISTS order_data (
id int(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
cus_id int(20) NOT NULL,
ITEM varchar(255) NOT NULL,
HSN varchar(50) NOT NULL,
QTY int(15) NOT NULL,
RATE decimal(40,2) NOT NULL,
S_C_GST decimal(30,2) NOT NULL,
TOTAL decimal(50,2) NOT NULL,
_DATE timestamp NOT NULL DEFAULT current_timestamp(),
**CONSTRAINT <FK_NAME>** FOREIGN KEY(cus_id) REFERENCES customers_data(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Making the table "at the same time" is not the problem you need to solve, (it's not possible anyway).
You can't make a foreign key if the data type is different from the data type of the referenced column.
order_data.cus_id is an INT column.
customers_data.id is an INT UNSIGNED column.
Change either one or the other data type, so they are the same.

mysql error 1215 cannot add foreign key contraint

DROP TABLE IF EXISTS desk;
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS authority;
CREATE TABLE authority
(
authorityId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
deskId INT DEFAULT 0,
authorityName VARCHAR(50) NOT NULL,
descriptions VARCHAR(100) NOT NULL,
userLevel TINYINT NOT NULL,
actions VARCHAR(300) DEFAULT NULL,
setDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE desk
(
deskId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
deskName CHAR(50) NOT NULL,
deskLink VARCHAR(100) NOT NULL,
details VARCHAR(350) DEFAULT NULL,
setDate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
closeDate TIMESTAMP DEFAULT NULL,
userId INT DEFAULT NULL,
status TINYINT(1) DEFAULT 0
);
CREATE TABLE user
(
userId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
userName CHAR(150) NOT NULL,
password VARCHAR(500) NOT NULL,
department VARCHAR(150) DEFAULT NULL,
deskId INT NOT NULL,
status TINYINT(1) DEFAULT NULL,
userLevel TINYINT NOT NULL,
FOREIGN KEY (deskId) REFERENCES desk (deskId) ON DELETE CASCADE,
FOREIGN KEY (userLevel) REFERENCES authority (userLevel)
);
Error while executing query.
Error Code: 1215 .Cannot add foreign key contraint
I have tried many way but still cannot solve the problem, i tried change userLevel type to INT both table user and authority but nothing went to better
I really not know how to fix this problem, please help
Follow below steps
1) You must change your second query to
DROP TABLE IF EXISTS desk;
CREATE TABLE desk
(
deskId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
deskName CHAR(50) NOT NULL,
deskLink VARCHAR(100) NOT NULL,
details VARCHAR(350) DEFAULT NULL,
setDate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
closeDate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
userId INT DEFAULT NULL,
status TINYINT(1) DEFAULT 0
);
2) As your column authority.userLevel is not a primary key and you want to use it as foreign key in other table you need to create index on authority.userLevel column
use below query
ALTER TABLE `authority` ADD INDEX `UserLevelIndex` (`userLevel`);
3) Run your third query as it is to create user table
Run Following queries
DROP TABLE IF EXISTS desk;
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS authority;
CREATE TABLE authority
(
authorityId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
deskId INT DEFAULT 0,
authorityName VARCHAR(50) NOT NULL,
descriptions VARCHAR(100) NOT NULL,
userLevel TINYINT NOT NULL,
actions VARCHAR(300) DEFAULT NULL,
setDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
index `cr_index` (userLevel)
);
CREATE TABLE desk
(
deskId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
deskName CHAR(50) NOT NULL,
deskLink VARCHAR(100) NOT NULL,
details VARCHAR(350) DEFAULT NULL,
setDate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
closeDate TIMESTAMP DEFAULT '0000-00-00 00:00:00',
userId INT DEFAULT NULL,
status TINYINT(1) DEFAULT 0
);
CREATE TABLE `user`
(
userId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
userName CHAR(150) NOT NULL,
password VARCHAR(500) NOT NULL,
department VARCHAR(150) DEFAULT NULL,
deskId INT NOT NULL,
status TINYINT(1) DEFAULT NULL,
userLevel TINYINT NOT NULL,
FOREIGN KEY (deskId) REFERENCES desk (deskId) ON DELETE CASCADE,
FOREIGN KEY (userLevel) REFERENCES authority (userLevel)
);
In your query you write timestamp default value NULL and you can create a non index key userLevel as a foreign key so from your query remove default value or change the default value 0000-00-00 00:00:00(in desk table) and add index in userLevel column (in authority table)
I hope this will work for you

Duplicate data is inserted with unique index

I have a table called users with 4 unique columns and when I insert data in email it doesn't give me any error and inserts the data even when when the same value already exists in that column.
Here is my database structure:
$user = "CREATE TABLE IF NOT EXISTS users(
id INT UNSIGNED AUTO_INCREMENT,
fb_id BIGINT UNSIGNED NULL,
google_id BIGINT UNSIGNED NULL,
fname VARCHAR(255) NOT NULL,
lname VARCHAR(255) NULL,
email VARCHAR(320) NOT NULL,
username VARCHAR(20) NULL,
password VARCHAR(255) NULL,
access_token TEXT NULL,
type ENUM('facebook','google','site') NOT NULL,
gender ENUM('m','f','o') NULL,
reg_date DATE NOT NULL,
token_expire DATETIME NULL,
PRIMARY KEY(id),
UNIQUE(email,username,fb_id,google_id)
)";
But, when I create my table with following structure:
$user = "CREATE TABLE IF NOT EXISTS users(
id INT UNSIGNED AUTO_INCREMENT,
fb_id BIGINT UNSIGNED NULL UNIQUE,
google_id BIGINT UNSIGNED NULL UNIQUE,
fname VARCHAR(255) NOT NULL,
lname VARCHAR(255) NULL,
email VARCHAR(320) NOT NULL UNIQUE,
username VARCHAR(20) NULL UNIQUE,
password VARCHAR(255) NULL,
access_token TEXT NULL,
type ENUM('facebook','google','site') NOT NULL,
gender ENUM('m','f','o') NULL,
reg_date DATE NOT NULL,
token_expire DATETIME NULL,
PRIMARY KEY(id)
)";
It gives me an error when there is a duplicate entry.
Creating table with any of those methods doesn't give any error. After creating the tables I have verified with phpmyadmin that all those columns have unique index in both methods.
Akash, in the 1st create table, the composite (combination) is unique. If you want them individually to be unique, separate them into ... separate UNIQUE key statements, like in the 2nd.
Let's say the bottom of your first table read this
PRIMARY KEY(id),
UNIQUE KEY(email,username,fb_id,google_id)
Then there is nothing wrong with these two rows existing in the composite index:
'akash#gmail.com','Akash',101,102
and
'akash#gmail.com','Akash2',101,102

relational database queries are not working mysql

I am trying to create a relational database in MySql but i am getting an error and I really cant figure out what’s wrong with my query.
Below is the error is get :
Error Code : 1072
Key column 'user_id' doesn't exist in table
(0 ms taken)
Here is my query :
CREATE TABLE tish_user(
user_id int(11) NOT NULL Auto_increment,
username varchar(30) NOT NULL,
Password varchar(41) NOT NULL,
Previllage VARCHAR(20) NOT NULL,
date_created datetime,
primary key (user_id )
)ENGINE=InnoDB;
CREATE TABLE tish_images(
image_id int(11) not null auto_increment,
image_name varchar(100) not null,
image_profile numeric(1) default 0,
FOREIGN KEY(user_id)REFERENCES tish_user(user_id)on update cascade,
primary key (image_id)
)ENGINE=InnoDB;
CREATE TABLE tish_clientinfor(
client_id int(11) not null auto_increment,
title varchar(11) not null,
firstname varchar(30) not null,
lastname varchar(30) not null,
client_code varchar(30) not null,
date_registered timestamp Default CURRENT_TIMESTAMP,
FOREIGN KEY(user_id)REFERENCES tish_user(user_id)on update cascade,
primary key (client_id)
)ENGINE=InnoDB;
You do not have a user_id column in tish_clientinfor as referenced by FOREIGN KEY(user_id).... Did you perhaps mean to add one?
CREATE TABLE tish_clientinfor(
client_id int(11) not null auto_increment,
title varchar(11) not null,
firstname varchar(30) not null,
lastname varchar(30) not null,
client_code varchar(30) not null,
date_registered timestamp Default CURRENT_TIMESTAMP,
user_id int(11) not null, --this was the missing column
FOREIGN KEY(user_id)REFERENCES tish_user(user_id)on update cascade,
primary key (client_id)
)ENGINE=InnoDB;
The same is true for table tish_images.