Sort soccer/football leaderboard table with direct matches - mysql

I'm going crazy to get a sorted leaderbord for my project. I need a help because I have to sort the table by points, goal difference and direct matches. My problem is direct matches.
MySQL version: 5.7.29
Here the tables structures and some example data:
CREATE TABLE `matches` (
`id` bigint(20) UNSIGNED NOT NULL,
`club_id_home` bigint(20) UNSIGNED NOT NULL,
`goals_home` tinyint(3) UNSIGNED NOT NULL DEFAULT '0',
`club_id_away` bigint(20) UNSIGNED NOT NULL,
`goals_away` tinyint(3) UNSIGNED NOT NULL DEFAULT '0',
`competition_id` bigint(20) UNSIGNED DEFAULT NULL,
`round` smallint(5) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `matches` (`id`, `club_id_home`, `goals_home`, `club_id_away`, `goals_away`, `competition_id`, `round`) VALUES
(1, 1, 3, 2, 2, 1, 1),
(2, 3, 0, 4, 0, 1, 1),
(3, 3, 1, 1, 1, 1, 1),
(4, 4, 1, 2, 0, 1, 1);
CREATE TABLE `leaderboards` (
`id` bigint(20) UNSIGNED NOT NULL,
`club_id` bigint(20) UNSIGNED NOT NULL,
`competition_id` bigint(20) UNSIGNED DEFAULT NULL,
`points` tinyint(3) UNSIGNED NOT NULL,
`wins` tinyint(3) UNSIGNED NOT NULL,
`losses` tinyint(3) UNSIGNED NOT NULL,
`draws` tinyint(3) UNSIGNED NOT NULL,
`goals_for` tinyint(3) UNSIGNED NOT NULL,
`goals_against` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `leaderboards` (`id`, `club_id`, `competition_id`, `points`, `wins`, `losses`, `draws`, `goals_for`, `goals_against`) VALUES
(1, 1, 1, 4, 1, 1, 0, 4, 3),
(2, 2, 1, 0, 0, 0, 2, 2, 4),
(3, 3, 1, 2, 0, 2, 0, 1, 1),
(4, 4, 1, 4, 1, 1, 0, 1, 0);
So I have to check points (easy) and goal difference (easy) from leaderboards table, and direct matches from matches table so that if Club A and Club B have same points I have to check if Club A won or lost (or tied) against Club B.
So in my example I would like to see a leaderboard sorted like this:
club_id 4 | points: 4 | goals difference: 1
club_id 1 | points: 4 | goals difference: 1
club_id 3 | points: 2 | goals difference: 0
club_id 2 | points: 0 | goals difference: -2
Club 4 is first because it won the direct match against club 1.
How can I do it? Is it possible?
Thank you in advance!

Related

MySQL divide calculation from two tables

for my page I have to divide values ​​from two tables.
I get the first value of the calculation from table one (game), where two values ​​are added to one. From table two (game_stats) I get the second value of the invoice. The values ​​Rounds and Kills should now be divided and saved or updated in the table game_stats_more as a value.
My current problem is that when I calculate the values ​​I get an error that the AS values ​​are not recognized. Where did I get my Select error?
SELECT SUM(game.match_score_team_1 + game.match_score_team_2) AS Rounds, game_stats.match_stats_kills AS Kills, Rounds / Kills AS KPR FROM game INNER JOIN game_stats WHERE game.match_id = 1 AND game_stats.user_id = 1
Error Message:
#1054 - Unknown table field 'Rounds' in field list
Sample schema:
CREATE TABLE `game` (
`match_id` int(3) NOT NULL,
`team_id` int(3) NOT NULL,
`match_team_2` varchar(255) COLLATE utf8_german2_ci NOT NULL,
`match_score_team_1` int(2) NOT NULL,
`match_score_team_2` int(2) NOT NULL,
`match_score_role_id` int(3) NOT NULL,
`match_role_id` int(3) NOT NULL,
`date` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_german2_ci;
INSERT INTO `game` (`match_id`, `team_id`, `match_team_2`, `match_score_team_1`, `match_score_team_2`, `match_score_role_id`, `match_role_id`, `date`) VALUES
(1, 7, 'TestGegner', 7, 2, 1, 1, '2020-06-10'),
CREATE TABLE `game_stats` (
`match_stats_id` int(3) NOT NULL,
`match_id` int(3) NOT NULL,
`user_id` int(3) NOT NULL,
`match_stats_kills` int(2) NOT NULL,
`match_stats_deaths` int(2) NOT NULL,
`match_stats_entry_kill` int(2) NOT NULL,
`match_stats_entry_death` int(2) NOT NULL,
`match_stats_clutch` int(2) NOT NULL,
`match_stats_plants` int(2) NOT NULL,
`match_stats_hs` int(2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_german2_ci;
INSERT INTO `game_stats` (`match_stats_id`, `match_id`, `user_id`, `match_stats_kills`, `match_stats_deaths`, `match_stats_entry_kill`, `match_stats_entry_death`, `match_stats_clutch`, `match_stats_plants`, `match_stats_hs`) VALUES
(1, 1, 1, 7, 5, 1, 3, 1, 4, 4),
(2, 1, 2, 6, 6, 2, 2, 0, 1, 3);
CREATE TABLE `game_stats_more` (
`game_stats_id` int(3) NOT NULL,
`game_id` int(3) NOT NULL,
`game_stats_more_kpr` int(3) NOT NULL,
`game_stats_more_hsp` int(3) NOT NULL,
`game_stats_more_kd` int(3) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_german2_ci;
INSERT INTO `game_stats_more` (`game_stats_id`, `game_id`, `game_stats_more_kpr`, `game_stats_more_hsp`, `game_stats_more_kd`) VALUES
(1, 1, 0, 0, 0);
You cannot use alias defined for field in same select statement
SELECT (game.match_score_team_1 + game.match_score_team_2) AS Rounds,
game_stats.match_stats_kills AS Kills,
(game.match_score_team_1 + game.match_score_team_2) /
game_stats.match_stats_kills AS KPR
FROM game
INNER JOIN game_stats ON game.match_id=game_stats.match_id
WHERE game.match_id = 1 AND game_stats.user_id = 1

Calculating sum of a values after join

I have these tables:
CREATE TABLE `items` (
`itemId` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`itemCategoryId` mediumint(8) unsigned DEFAULT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`itemId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `orders` (
`orderId` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`customerId` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`orderId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `orders_items` (
`orderItemId` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`orderId` mediumint(8) unsigned NOT NULL,
`itemId` mediumint(8) unsigned NOT NULL,
`price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00',
PRIMARY KEY (`orderItemId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `order_items_quantity` (
`orderItemId` mediumint(8) unsigned NOT NULL,
`size` tinyint(3) unsigned DEFAULT NULL,
`quantity` smallint(5) unsigned NOT NULL,
UNIQUE KEY `unique` (`orderItemId`,`size`,`quantity`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `items` (`itemId`, `itemCategoryId`, `name`)
VALUES
(1, 1, 'Jeans Model A (Category Jeans)'),
(2, 1, 'Jeans Model B (Category Jeans)'),
(3, 2, 'T-Shirt Model A (Category T-Shirt)');
INSERT INTO `orders` (`orderId`, `customerId`)
VALUES
(1, 1),
(2, 2),
(3, 1);
INSERT INTO `orders_items` (`orderItemId`, `orderId`, `itemId`)
VALUES
(1, 1, 1),
(2, 1, 2),
(3, 2, 1),
(4, 2, 2),
(5, 3, 1),
(6, 3, 3);
INSERT INTO `order_items_quantity` (`orderItemId`, `size`, `quantity`)
VALUES
(1, 1, 2),
(1, 2, 3),
(2, 1, 3),
(2, 2, 5),
(3, 1, 1),
(3, 2, 2),
(4, 1, 1),
(4, 2, 1),
(5, 1, 4),
(6, 1, 3);
I can't merge 'order_items' with 'order_items_quantity' because I have other fields in the first table about the items regardless the size (es. their prices in that moment) that would be wasted disk space if I repeat them in only one table.
I need a query to get the sum of all the ordered quantities of any item of a certain category by each customer regerdless of the size. Something like:
customerId itemCategoryId total_quantity_ordered
1 1 17
2. 1 5
2. 2. 3
I wrote this query:
SELECT total_quantities.total_quantity_ordered, orders.customerId, items.itemCategoryId FROM orders
JOIN (
SELECT orders_items.orderId, SUM(order_items_quantity.quantity) AS total_quantity_ordered
FROM orders_items
JOIN order_items_quantity ON order_items_quantity.orderItemId=orders_items.orderItemId
GROUP BY orders_items.orderId
) AS total_quantities ON total_quantities.orderId=orders.orderId
JOIN orders_items ON orders_items.orderId=orders.orderId
JOIN items ON items.itemId=orders_items.itemId
GROUP BY orders.customerId, items.itemCategoryId
but it selects only the first order of every customer containing that categoryId. Any help is appreciated.
SQL Fiddle: https://www.db-fiddle.com/f/bnxomXfobBN25nTJvASVdL/0
You don't need the subquery:
SELECT o.customerId, i.itemCategoryId SUM(q.quantity) AS total_quantity_ordered
FROM orders o
INNER JOIN orders_items oi ON oi.orderId=o.orderId
JOIN order_items_quantity q ON oi.orderItemId=q.orderItemId
JOIN items i ON i.itemId=oi.itemId
GROUP BY o.customerId, i.itemCategoryId

Multiple left joins show distinct result with last date

I want to build a discussion board. Therefore I have 3 tables: t_posts, t_boards, t_board_categories. Posts contain Threads (where post_post_id IS NULL) and replies to threads (where post_post_id IS NOT NULL), so it is self-referring. Now I want to show the last 5 posts (Threads and/or Replies) in all boards of all categories. The sql currently looks like this:
SELECT p.post_id,
p.post_board_id,
p.post_user_id,
p2.post_title,
bc.bc_name,
Max(p.post_date) post_date
FROM t_posts p
LEFT JOIN t_posts p2
ON ( p2.post_post_id IS NULL
AND ( p2.post_id = p.post_id
OR p.post_post_id = p2.post_id ) )
LEFT JOIN t_boards b
ON b.board_id = p.post_board_id
LEFT JOIN t_board_categories bc
ON bc.bc_id = b.board_bc_id
WHERE p.post_system_id = '1'
AND p.post_deleted = 0
AND bc.bc_deleted = 0
AND b.board_deleted = 0
GROUP BY p.post_id,
p2.post_id
ORDER BY p2.post_date DESC
LIMIT 5
The result is almost what I want, except of, that multiple replies in one thread will lead to showing only that one thread. What I want is 5 different threads to be shown with the most recent answers, not only one thread 5 times.
I join t_posts p2 for showing the original thread title.
I also tried adding DISTINCT p2.post_id to the SELECT, but it does not change anything.
Schema:
CREATE TABLE `t_board_categories` (
`bc_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`bc_name` varchar(128) COLLATE utf8_unicode_ci DEFAULT '',
`bc_prio` int(11) NOT NULL DEFAULT '0',
`bc_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`bc_deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`bc_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `t_boards` (
`board_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`board_bc_id` int(10) unsigned DEFAULT NULL,
`board_name` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL,
`board_subtitle` text COLLATE utf8_unicode_ci,
`board_prio` int(11) NOT NULL DEFAULT '0',
`board_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`board_deleted` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`board_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `t_posts` (
`post_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_user_id` bigint(20) unsigned DEFAULT NULL,
`post_title` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`post_text` text COLLATE utf8_unicode_ci NOT NULL,
`post_post_id` bigint(20) unsigned DEFAULT NULL,
`post_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`post_board_id` int(10) unsigned NOT NULL DEFAULT '0',
`post_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`post_deleted` int(2) NOT NULL DEFAULT '0',
PRIMARY KEY (`post_id`)
) ENGINE=InnoDB AUTO_INCREMENT=205 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
INSERT INTO `t_board_categories` (`bc_id`, `bc_name`, `bc_prio`, `bc_system_id`, `bc_deleted`) VALUES (1, 'Test-Category', '1', '1', '0');
INSERT INTO `t_boards` (`board_id`, `board_bc_id`, `board_name`, `board_subtitle`, `board_prio`, `board_system_id`, `board_deleted`) VALUES (1, '1', 'Test-Board', 'Board Subtitle', '1', '1', '0');
INSERT INTO `t_posts` (`post_id`, `post_user_id`, `post_title`, `post_text`, `post_post_id`, `post_date`, `post_board_id`, `post_system_id`, `post_deleted`) VALUES
(1, 14, 'Thread 1', 'Test1', NULL, '2019-05-22 00:18:25', 1, 1, 0),
(2, 14, 'Thread 2', 'Test2', NULL, '2019-05-22 00:18:44', 1, 1, 0),
(3, 14, 'Thread 3', 'Test 3', NULL, '2019-05-22 00:18:51', 1, 1, 0),
(4, 19, 'Thread 4', 'Test 4', NULL, '2019-05-22 00:19:02', 1, 1, 0),
(5, 19, 'Thread 5', 'Test 5', NULL, '2019-05-22 00:19:07', 1, 1, 0),
(6, 19, 'Thread 6', 'Test 6', NULL, '2019-05-22 00:19:15', 1, 1, 0),
(7, 14, 'Reply', 'A', 5, '2019-05-22 00:19:46', 1, 1, 0),
(8, 14, 'Reply', 'B', 5, '2019-05-22 00:19:47', 1, 1, 0),
(9, 14, 'Reply', 'C', 5, '2019-05-22 00:19:49', 1, 1, 0);
Expected Result: One row for thread 1-5 with user-id and date of last reply (userid:14, date: 2019-05-22 00:19:49 for Thread 5, for Thread 1-4 last date is thread-date, userid is thread author userid)
I worked on this the whole evening, would be great to get some help. Thank you in advance!
Your sample data suggests, that post levels cannot span more than two levels (post_post_id cannot be an ID of a post where post_post_id isn't null). Assuming that, you can try to use correlated subqueries getting the sub posts and the post for a post, order them by their date descending and use LIMIT to pick the top one. Also sort the main query by the date of the last sub post descending and use LIMIT to get the top 5. Something along the lines of:
SELECT bc1.bc_id,
bc1.bc_name,
b1.board_id,
b1.board_name,
p1.post_id,
p1.post_title,
(SELECT p2.post_title
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_title,
(SELECT p2.post_user_id
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_user_id,
(SELECT p2.post_date
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_date
FROM t_posts p1
INNER JOIN t_boards b1
ON b1.board_id = p1.post_board_id
INNER JOIN t_board_categories bc1
ON bc1.bc_id = b1.board_bc_id
WHERE p1.post_post_id IS NULL
ORDER BY last_post_date DESC
LIMIT 5;
db<>fiddle

MySql. 'group by' by parts

there is a table
CREATE TABLE geography_schedule (
id int(10) UNSIGNED NOT NULL,
geography_address_id int(10) UNSIGNED NOT NULL,
geography_city_id int(10) UNSIGNED NOT NULL,
sort int(5) UNSIGNED NOT NULL DEFAULT '500',
site varchar(5) NOT NULL DEFAULT 'site',
group_id int(10) NOT NULL DEFAULT '0',
day int(10) NOT NULL DEFAULT '1',
all_day tinyint(2) NOT NULL DEFAULT '0',
freeday int(10) NOT NULL DEFAULT '0',
from varchar(5) NOT NULL DEFAULT '09:00',
to varchar(5) NOT NULL DEFAULT '18:00',
timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_update timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO geography_schedule (from, to, geography_address_id, day_from, day_to, group_id) VALUES
('09:00', '18:00', 533, 1, 1, 1),
('09:00', '18:00', 533, 2, 2, 1),
('11:00', '17:00', 533, 3, 3, 1),
('11:00', '17:00', 533, 4, 4, 1),
('09:00', '18:00', 533, 5, 5, 1),
('10:00', '17:00', 533, 6, 6, 1),
('09:00', '18:00', 533, 7, 7, 1);
I have a mysql query from this table enter image description here
SELECT `from`,`to`, `geography_address_id`, MIN(`day`) as `day_from`
,MAX(`day`) as `day_to`,`group_id`
FROM `geography_schedule`
WHERE `geography_address_id` = 533
GROUP BY `from`,`to`
ORDER BY `geography_schedule`.`day` ASC
result:
I need to group by lines 9:00 - 18:00 to save days day_from & day_to in proper order.
Is it possible to use GROUP BY in such a way it will give the result like this?

how to calculate percentage and generate below result

I have a table schema
CREATE TABLE `charge` (
`charge_id` int(11) NOT NULL AUTO_INCREMENT,
`selling_date` date DEFAULT NULL,
`amount` decimal(10,2) DEFAULT NULL,
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`charge_type_id` int(11) DEFAULT NULL,
PRIMARY KEY (`charge_id`)
);
CREATE TABLE `charge_type` (
`charge_type_id` int(11) NOT NULL AUTO_INCREMENT,
`charge_type` varchar(20) NOT NULL,
`is_deleted` tinyint(1) DEFAULT '0',
PRIMARY KEY (`charge_type_id`)
);
CREATE TABLE `charge_type_tax_list` (
`tax_type_id` int(11) NOT NULL,
`charge_type_id` int(11) NOT NULL,
PRIMARY KEY (`tax_type_id`,`charge_type_id`)
);
CREATE TABLE `tax_type` (
`tax_type_id` int(11) NOT NULL AUTO_INCREMENT,
`tax_type` varchar(35) NOT NULL,
`percentage` decimal(5,4) NOT NULL DEFAULT '0.0000',
`is_deleted` tinyint(1) DEFAULT '0',
PRIMARY KEY (`tax_type_id`)
);
INSERT INTO charge (
`selling_date`,
`amount`,
`is_deleted`,
`charge_type_id`
)
VALUES
("2013-12-01", 50, 0, 1),
("2013-12-01", 20, 0, 2),
("2013-12-02", 40, 0, 1),
("2013-12-02", 30, 0, 3),
("2013-12-02", 30, 1, 1),
("2013-12-03", 10, 0, 1);
INSERT INTO charge_type (
`charge_type_id`,
`charge_type`,
`is_deleted`
)
VALUES
(1, "room charge", 0),
(2, "snack charge", 0),
(3, "deleted charge", 1);
INSERT INTO charge_type_tax_list (
`tax_type_id`,
`charge_type_id`
)
VALUES
(1, 1),
(2, 1),
(3, 1),
(1, 2),
(1, 3);
INSERT INTO tax_type (
`tax_type_id`,
`tax_type` ,
`percentage`,
`is_deleted`
)
VALUES
(1, "GST", 0.05, 0),
(2, "HRT", 0.04, 0),
(3, "DELETED TAX", 0.10, 1);
I want you to produce a query that lists all charges and tax-calculated totals
With the given schema, your query should produce:
Selling Date Charge Type Amount Tax
2013-12-01 Room Charge 50.00 4.50
2013-12-01 Snack Charge 20.00 1.00
2013-12-02 Room Charge 40.00 3.60
2013-12-03 Room Charge 10.00 0.90
Do not display charges that are deleted (is_deleted is flagged)
Do not display charges that have charge_types that are deleted (is_deleted is flagged)
Do not consider tax_type that is deleted (is_deleted), but the containing charge_type should still be displayed)
Please help me I need it urgently.Thanks
Please read on MySQL Join Made Easy to understand how joins are used. Here is a query that should give the result you want by joining the tables on the common attributes.
SELECT A.`selling_date` AS `Selling Date`, B.`charge_type` AS `Charge Type`
, A.`amount` AS `Amount`, (A.`amount` * D.`percentage`) AS `Tax` FROM
`charge` A LEFT JOIN
`charge_type` B ON A.`charge_type_id`=B.`charge_type_id` INNER JOIN
`charge_type_tax_list` C ON B.`charge_type_id`=C.`charge_type_id`
INNER JOIN `tax_type` D ON C.`tax_type_id`=D.`tax_type_id`
WHERE
A.`is_deleted`=0 AND B.`is_deleted`=0 AND
D.`is_deleted`=0;
Here is an SQL FIDDLE DEMO
This query below will get the result that you want
select charge.selling_date as SellingDate,
charge.amount as Amount,
charge_type.charge_type as ChargeType,
sum(charge.amount * tax_type.percentage) as Tax
From charge
inner join charge_type on charge.charge_type_id=charge_type.charge_type_id,
tax_type
where charge.is_deleted=0 and charge_type.is_deleted=0 and tax_type.is_deleted=0
group by charge.selling_date, charge.amount,charge_type.charge_type