redisplaying data from a table in mySQL - mysql

I am trying to redisplay the data from a table
currently the data in the table goes as
__________________________________________
| UserMeta |
|__________________________________________|
| id | userID | orgID | keyType | keyData |
|____|________|_______|__________|_________|
| 1 | 1 | 1 | UserName | Scarlet |
| 2 | 1 | 1 | Age | 23 |
| 3 | 2 | 2 | UserName | Diana |
| 4 | 2 | 2 | Age | 27 |
| 5 | 3 | 1 | UserName | Kevin |
| 6 | 3 | 1 | Age | 18 |
|____|________|_______|__________|_________|
I'd like to be able to format it to the following
_________________________________
| vUserMeta |
|_________________________________|
| UserID | orgID | UserName | Age |
|________|_______|__________|_____|
| 1 | 1 | Scarlet | 23 |
| 2 | 2 | Diana | 27 |
| 3 | 1 | Kevin | 18 |
|________|_______|__________|_____|

One approach would be to join UserMeta on itself as follows:
SELECT u.userID AS UserID,
u.orgID AS orgID,
u.keyData AS UserName,
v.keyData AS Age
FROM UserMeta u
JOIN UserMeta v
ON u.userID = v.userID
AND u.keyType = 'UserName'
AND v.keyType = 'Age'

Related

MySQL select users who was in range of dates

Hello :) I need to create sql which will calculate advances for user but only for that one who was in work. Tables looks like:
users:
| id | firstName | lastName |
| -- | --------- | -------- |
| 1 | John 1 | Test 1 |
| 2 | John 2 | Test 2 |
| 3 | John 3 | Test 3 |
| 4 | John 4 | Test 4 |
users_advances:
| id | user_id | amount | d_add | status_id |
| -- | ------- | ------ | ---------- | --------- |
| 1 | 1 | 100 | 2022-07-09 | 1 |
| 2 | 1 | 50 | 2022-07-10 | 2 |
| 3 | 2 | 100 | 2022-07-03 | 1 |
| 4 | 2 | 50 | 2022-07-05 | 2 |
| 5 | 2 | 100 | 2022-03-09 | 1 |
| 6 | 1 | 50 | 2022-07-02 | 2 |
users_arrivals
| id | user_id | start_date | end_date |
| -- | ------- | ---------- | ---------- |
| 1 | 1 | 2022-09-01 | 2022-09-30 |
| 2 | 2 | 2022-09-22 | 2022-09-25 |
| 3 | 3 | 2022-09-19 | 2022-09-25 |
I created SQL
SELECT u.id AS user_id, CONCAT(u.firstName, SPACE(1), u.lastName) AS fullName, IFNULL(SUM(uz.amount), 0) AS suma
FROM users u
LEFT JOIN users_advances uz ON uz.user_id = u.id AND (uz.d_add BETWEEN '2022-09-19' AND '2022-09-25') AND ((uz.status_id = 1) OR (uz.status_id = 2))
LEFT JOIN users_arrivals po ON po.user_id = u.id
WHERE po.start_date <= '2022-09-19' AND po.end_date >= '2022-09-24'
GROUP BY u.id
but it doesnt return me user 2 who had start_date at 2022-09-22.

I want to ranking result with city based in mysql

I want to ranking result with city based in mysql
table1:-users
| user_id | marks |
--------------------
| 1 | 10 |
| 5 | 10 |
| 5 | 50 |
| 3 | 15 |
| 4 | 10 |
| 2 | 10 |
| 6 | 10 |
| 6 | 50 |
| 4 | 15 |
| 4 | 10 |
table:-2 users details
| user_id | city |
--------------------
| 1 | newdelhi |
| 2 | kolkata |
| 3 | mumbai |
| 4 | newdelhi |
| 5
| 6 | newdelhi |
I want to result like this:
| user_id | points |
--------------------
| 6 | 60 |
| 4 | 35 |
| 1 | 10 |
Try this :
SELECT
users.user_id
,SUM(users.marks) AS points
FROM
users
INNER JOIN
users_details ON users.user_id = users_details.user_id
WHERE
users_details.city = 'newdelhi'
GROUP BY
user_id

MYSQL Complex Join one-to-many

I have the following tables:
clients:
| id | name | code | zone |
--------------------------------
| 1 | client 1 | a1b1 | zone1|
| 2 | client 2 | a2b2 | zone2|
contacts:
| id_contact | first_name | last_name |
----------------------------------------
| 11 | first1 | last1 |
| 22 | first2 | last2 |
| 33 | first3 | last3 |
| 44 | first4 | last4 |
client_contacts:
| id_client | id_contact |
--------------------------
| 1 | 11 |
| 1 | 22 |
| 1 | 33 |
| 2 | 11 |
| 2 | 44 |
offers:
| id_offer | id_client | value |
--------------------------
| 111 | 1 | 100 |
| 222 | 1 | 200 |
| 333 | 1 | 300 |
| 444 | 2 | 400 |
I would like through a optimal select to obtain:
| id_client | name | code | zone | contacts_pers | total_offer_value |
----------------------------------------------------------------------------
| 1 | client 1 | a1b1 | zone1 | first1 last1; | 600 |
first2 last2;
first3 last3;
| 2 | client 2 | a2b2 | zone2 | first1 last1; | 400 |
first4 last4;
I know how to get the desired result with "group_concat" and stored procedures for "total_offer_value". But how to get the desired result from a single efficient select?
SELECT c.id, c.name, c.code, c.zone, GROUP_CONCAT(DISTINCT CONCAT(co.first_name, " ", c.last_name) SEPARATOR ";") AS contact_pers, func_total_offer_value(c.id) AS total_offer_value
FROM clients c
LEFT OUTER JOIN (client_contacts cc, contacts co) ON ( c.id = cc.id_client AND cc.id_contact = co.id_contact )
GROUP BY c.id

How can I update two different tables in one query?

I have two tables like this:
// users
+----+--------+----------------------------+------------------+
| id | name | email | notification_num |
+----+--------+----------------------------+------------------+
| 1 | John | John134#gmail.com | 4 |
| 2 | Peter | matrix_peter#ymail.com | 2 |
| 3 | Jack | jk_43m#gmail.com | 6 |
+----+--------+----------------------------+------------------+
// notifications
+----+---------+---------+------+
| id | post_id | user_id | seen |
+----+---------+---------+------+
| 1 | 4325 | 2 | NULL |
| 2 | 8765 | 3 | NULL |
| 3 | 5454 | 3 | 1 |
| 4 | 4346 | 2 | NULL |
| 5 | 3243 | 1 | 1 |
| 6 | 3246 | 2 | 1 |
| 7 | 3764 | 3 | 1 |
+----+---------+---------+------+
Ok, All I have is just a user_id. For example :user_id = 2, And then I want this output:
// users
+----+--------+----------------------------+------------------+
| id | name | email | notification_num |
+----+--------+----------------------------+------------------+
| 1 | John | John134#gmail.com | 4 |
| 2 | Peter | matrix_peter#ymail.com | 0 |
| 3 | Jack | jk_43m#gmail.com | 6 |
+----+--------+----------------------------+------------------+
// notifications
+----+---------+---------+------+
| id | post_id | user_id | seen |
+----+---------+---------+------+
| 1 | 4325 | 2 | 1 |
| 2 | 8765 | 3 | NULL |
| 3 | 5454 | 3 | 1 |
| 4 | 4346 | 2 | 1 |
| 5 | 3243 | 1 | 1 |
| 6 | 3246 | 2 | 1 |
| 7 | 3764 | 3 | 1 |
+----+---------+---------+------+
As you see, I want to update users.cotification_num and set it to 0 (for such an user), and I also want to update notifications.seen and set all rows to 1 (for such an user). How can I do that?
I can do that by two different queries like this:
UPDATE users SET notification_num = 0 WHERE id = :user_id
UPDATE notifications SET seen = 1 WHERE seen is NULL and user_id = :user_id
But I want to know how can I do that by one query?
You can use a multiple-table UPDATE:
UPDATE users u LEFT JOIN notifications n ON n.user_id = u.id
SET u.notification_num = 0,
n.seen = 1
WHERE u.id = 2
You can join the tables together to UPDATE both in a single query:
UPDATE users, notifications
SET users.notification_num = 0
, notification.seen = 1
WHERE users.id = notifications.user_id AND
users.id = 2 AND
notifications.seen is NULL
Read here for more information. Another option would be to simply do 2 separate updates within a transaction:
START TRANSACTION;
UPDATE users SET notification_num = 0 WHERE id = 2;
UPDATE notifications SET seen = 1 WHERE user_id = 2 AND notifications.seen is NULL;
COMMIT;
Note that my schema is very slightly different from yours - but it makes very little difference...
DROP TABLE IF EXISTS users;
CREATE TABLE users
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL
,email VARCHAR(20) NOT NULL
,notification_num INT NOT NULL
);
INSERT INTO users VALUES
(1,'John','John134#gmail.com',4),
(2,'Peter','matrix_peter#ymail.com',2),
(3,'Jack','jk_43m#gmail.com',6);
DROP TABLE IF EXISTS notifications;
CREATE TABLE notifications
(post_id INT NOT NULL
,user_id INT NOT NULL
,seen TINYINT DEFAULT 0
,PRIMARY KEY(post_id,user_id)
);
INSERT INTO notifications VALUES
(4325,2,0),
(8765,3,0),
(5454,3,1),
(4346,2,0),
(3243,1,1),
(3246,2,1),
(3764,3,1);
SELECT * FROM notifications;
+---------+---------+------+
| post_id | user_id | seen |
+---------+---------+------+
| 3243 | 1 | 1 |
| 3246 | 2 | 1 |
| 3764 | 3 | 1 |
| 4325 | 2 | 0 |
| 4346 | 2 | 0 |
| 5454 | 3 | 1 |
| 8765 | 3 | 0 |
+---------+---------+------+
SELECT * FROM users;
+----+-------+----------------------+------------------+
| id | name | email | notification_num |
+----+-------+----------------------+------------------+
| 1 | John | John134#gmail.com | 4 |
| 2 | Peter | matrix_peter#ymail.c | 2 |
| 3 | Jack | jk_43m#gmail.com | 6 |
+----+-------+----------------------+------------------+
UPDATE users u
JOIN notifications n
ON n.user_id = u.id
SET u.notification_num = 0, n.seen = 1
WHERE u.id = 2;
SELECT * FROM users;
+----+-------+----------------------+------------------+
| id | name | email | notification_num |
+----+-------+----------------------+------------------+
| 1 | John | John134#gmail.com | 4 |
| 2 | Peter | matrix_peter#ymail.c | 0 |
| 3 | Jack | jk_43m#gmail.com | 6 |
+----+-------+----------------------+------------------+
SELECT * FROM notifications;
+---------+---------+------+
| post_id | user_id | seen |
+---------+---------+------+
| 3243 | 1 | 1 |
| 3246 | 2 | 1 |
| 3764 | 3 | 1 |
| 4325 | 2 | 1 |
| 4346 | 2 | 1 |
| 5454 | 3 | 1 |
| 8765 | 3 | 0 |
+---------+---------+------+

MYSQL add row and count from diffrent table

I have mysql database with two tables.
First (information)
+---------+------+----------+
| species | sex | user |
+---------+------+----------+
| bird | NULL | 1 |
| bird | f | 1 |
| cat | f | 1 |
| cat | m | 1 |
| dog | f | 1 |
| dog | m | 2 |
| hamster | f | 2 |
| snake | m | 1 |
+---------+------+----------+
Second (users)
+--------+-----+
| user | id |
+--------+-----+
| amy | 1 |
| dav | 2 |
| mot | 3 |
| mmm | 4 |
| aaw | 5 |
| dsa | 6 |
+--------+-----+
I want to count and show values from table "information" for each user row on table "users"
Like this
+---------+------+----------+
| user | id | count |
+---------+------+----------+
| amy | 1 | 6 |
| dav | 2 | 2 |
| mot | 3 | 0 |
| mmm | 4 | 0 |
| aaw | 5 | 0 |
| dsa | 6 | 0 |
+---------+------+----------+
How can I do this query?
select users.user, users.id, count (species.name)
from users left join species
on users.id = species.user
group by users.user, users.id
order by count (species.name) desc
Isn't it something like:
select u.user, u.id, count(i.user)
from user u
inner join information i on i.user = u.id
group by u.user, u.id