Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have problems extracting data from these tables. I have a statistics system where numbers are entered for employees every some days in the month - for the sake of example here are only two months but it will be a full year. I tried a join but I received doubled results + some employee can work on more accounts while others could work on only one...
employees:
+----+-------------+--+
| ID | Name | |
+----+-------------+--+
| 1 | John Doe | |
| 2 | Helen Price | |
| 3 | John Price | |
+----+-------------+--+
Account
+----+---------+--+
| ID | Name | |
+----+---------+--+
| 1 | fisher | |
| 2 | fisher1 | |
+----+---------+--+
January
+----+-------------+---------+----------+----------+----------+
| ID | Employee | Account | firstday | seconday | thirdday |
+----+-------------+---------+----------+----------+----------+
| 1 | John Doe | fisher | 2 | 4 | 6 |
| 2 | Helen Price | fisher | 1 | 1 | 1 |
| 3 | John Price | fisher1 | 1 | 2 | 1 |
| 4 | John Price | fisher | 1 | 1 | 1 |
+----+-------------+---------+----------+----------+----------+
February
+----+-------------+---------+-----------+----------+-----------+
| ID | Employee | Account | fourthday | eightday | secondday |
+----+-------------+---------+-----------+----------+-----------+
| 1 | John Doe | fisher | 1 | 4 | 6 |
| 2 | Helen Price | fisher | 1 | 1 | 2 |
| 3 | John Price | fisher1 | 1 | 2 | 1 |
| 4 | John Price | fisher | 1 | 1 | 1 |
+----+-------------+---------+-----------+----------+-----------+
My question is how can I write a query with the following result:
+----+-------------+---------+-----------------+------------------+--------+--+
| ID | Employee | Account | January(totals) | February(totals) | Totals | |
+----+-------------+---------+-----------------+------------------+--------+--+
| 1 | John Doe | fisher | 12 | 11 | 23 | |
| 2 | Helen Price | fisher | 3 | 4 | 7 | |
| 3 | John Price | fisher | 3 | 3 | 6 | |
+----+-------------+---------+-----------------+------------------+--------+--+
What you're wanting is a pivot-table of aggregate results from the different JOIN tables.
There are a couple of approaches, but one approach is using LEFT JOIN with aggregate subqueries to total your monthly results by each employee and account.
In your sample data, there is no correlation of Employee to Account outside of your Month tables. So the association needs to be created by using another subquery to create the correlation to join the monthly tables on. This will cause an association for every employee and every account unless a many-to-many table is created to create the association.
Lastly since your sample data is only showing a single Account (fisher), you would need to filter it somehow, which was not specified clearly in your question, so I added it in to the WHERE criteria.
Example: DB-Fiddle
SELECT
e.ID,
e.Name AS Employee,
e.Account,
COALESCE(janurary_totals.total, 0) AS `January(totals)`,
COALESCE(february_totals.total, 0) AS `February(totals)`,
COALESCE(janurary_totals.total, 0) + COALESCE(february_totals.total, 0) AS Totals
FROM (
SELECT e1.ID, e1.Name, a1.Name AS Account
FROM employees AS e1
LEFT JOIN Account AS a1
ON a1.ID IS NOT NULL
) AS e
LEFT JOIN (
SELECT
Employee,
Account,
SUM(firstday) + SUM(seconday) + SUM(thirdday) AS total
FROM January
GROUP BY Employee, Account
) AS janurary_totals
ON janurary_totals.Employee = e.Name
AND janurary_totals.Account = e.Account
LEFT JOIN (
SELECT
Employee,
Account,
SUM(fourthday) + SUM(eightday) + SUM(secondday) AS total
FROM February
GROUP BY Employee, Account
) AS february_totals
ON february_totals.Employee = e.Name
AND february_totals.Account = e.Account
WHERE e.Account = 'fisher'
Result
| ID | Employee | Account | January(totals) | February(totals) | Totals |
| --- | ----------- | ------- | --------------- | ---------------- | ------ |
| 1 | John Doe | fisher | 12 | 11 | 23 |
| 2 | Helen Price | fisher | 3 | 4 | 7 |
| 3 | John Price | fisher | 3 | 3 | 6 |
You could greatly simplify things, by refactoring the individual month tables into a single employee_entry table with an employee_id, account_id, amount and DATE columns, that you could use to query against to create the pivot-table. As it stands currently, there is no means of determining which year the values are recorded, which will cause confusion on subsequent year totals.
The single entry table would allow you to create a pivot-table using conditional aggregates.
SUM(CASE MONTH(date_column) WHEN # THEN amount_column ELSE 0 END) AS MonthTotal
Allowing you to filter and group the results as desired.
Example: DB-Fiddle
SELECT
e.`Name` AS Employee,
a.`Name` AS Account,
m.`Year`,
m.`January(totals)`,
m.`February(totals)`,
m.`Totals`
FROM (
SELECT
ee.employee_id,
ee.account_id,
YEAR(ee.`datetime`) AS `Year`,
SUM(CASE MONTH(ee.datetime) WHEN 1 THEN ee.amount ELSE 0 END) AS `January(totals)`,
SUM(CASE MONTH(ee.datetime) WHEN 2 THEN ee.amount ELSE 0 END) AS `February(totals)`,
SUM(ee.amount) AS `Totals`
FROM employee_entry AS ee
GROUP BY ee.employee_id, ee.account_id, `Year`
) AS m
LEFT JOIN employees AS e
ON e.ID = m.employee_id
LEFT JOIN Account AS a
ON a.ID = m.account_id
Result
| Employee | Account | Year | January(totals) | February(totals) | Totals |
| ----------- | ------- | ---- | --------------- | ---------------- | ------ |
| Helen Price | fisher | 2020 | 3 | 4 | 7 |
| John Doe | fisher | 2020 | 12 | 11 | 23 |
| John Price | fisher | 2020 | 3 | 3 | 6 |
| John Price | fisher1 | 2020 | 4 | 4 | 8 |
To perform the conversion, you create the employee_entry table, and insert your individual monthly tables into it, by specifying a date for each of the day columns.
CREATE TABLE employee_entry (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`employee_id` INTEGER,
`account_id` INTEGER,
`amount` INTEGER,
`datetime` DATE NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO employee_entry
(`employee_id`, `account_id`, `amount`, `datetime`)
(
SELECT e.ID, a.ID, j.firstday, '2020-01-01'
FROM `January` AS j
LEFT JOIN employees AS e
ON j.Employee = e.Name
LEFT JOIN Account AS a
ON j.Account = a.Name
)
UNION
(
SELECT e.ID, a.ID, j.seconday, '2020-01-02'
FROM `January` AS j
LEFT JOIN employees AS e
ON j.Employee = e.Name
LEFT JOIN Account AS a
ON j.Account = a.Name
)
UNION
(
SELECT e.ID, a.ID, j.thirdday, '2020-01-03'
FROM `January` AS j
LEFT JOIN employees AS e
ON j.Employee = e.Name
LEFT JOIN Account AS a
ON j.Account = a.Name
)
UNION
(
SELECT e.ID, a.ID, f.fourthday, '2020-02-04'
FROM `February` AS f
LEFT JOIN employees AS e
ON f.Employee = e.Name
LEFT JOIN Account AS a
ON f.Account = a.Name
)
UNION
(
SELECT e.ID, a.ID, f.eightday, '2020-02-08'
FROM `February` AS f
LEFT JOIN employees AS e
ON f.Employee = e.Name
LEFT JOIN Account AS a
ON f.Account = a.Name
)
UNION
(
SELECT e.ID, a.ID, f.secondday, '2020-02-02'
FROM `February` AS f
LEFT JOIN employees AS e
ON f.Employee = e.Name
LEFT JOIN Account AS a
ON f.Account = a.Name
);
Related
I have the following tables
table anag (customer registry)
id | surname | name | phone |
----------------------------------------------
1 | Brown | Jack | +3989265781 |
2 | Smith | Bill | +3954872358 |
3 | Rogers | Stan | +3912568453 |
4 | Pickford | Eric | +3948521358 |
----------------------------------------------
table levels (table that connects each customer to his salesperson. For database registration reasons, the link between customer and seller is given by the customer's telephone number)
id | client_phone | id_seller |
--------------------------------------
1 | +3989265781 | 4 |
2 | +3954872358 | 7 |
3 | +3912568453 | 7 |
4 | +3948521358 | 8 |
--------------------------------------
table orders (contains all purchases made by customers, of course)
id | id_client | id_item | id_seller | price | status |
--------------------------------------------------------------------
1 | 1 | 2 | 4 | 12.50 | 2 |
2 | 2 | 2 | 7 | 12.50 | 2 |
3 | 2 | 3 | 7 | 10.00 | 3 |
4 | 2 | 3 | 7 | 10.00 | 3 |
5 | 2 | 4 | 7 | 20.50 | 1 |
6 | 3 | 2 | 7 | 12.50 | 1 |
7 | 3 | 5 | 7 | 19.00 | 3 |
8 | 3 | 7 | 7 | 31.00 | 2 |
9 | 4 | 1 | 8 | 5.00 | 1 |
--------------------------------------------------------------------
What I'm trying to do is get from the JOIN of these tables a complete list by seller of his customers sorted in descending order by the amount spent on orders as long as the order status is 2 or 3
Something like this (example seller id 7):
id | surname | name | amaount |
----------------------------------------
3 | Rogers | Stan | 50.00 |
2 | Smith | Bill | 32.50 |
----------------------------------------
I have tried with this query which seems correct to me, but unfortunately it returns me error in fetch_assoc()
SELECT a.id, a.surname, a.name, o.amount FROM levels AS l
JOIN anag AS a ON a.phone = l.client_phone
JOIN {
SELECT id_client, SUM(price) AS amount FROM orders
WHERE id_seller = '7' AND (status = '2' OR status = '3') GROUP BY id_client
} AS o ON o.id_client = a.id
WHERE l.id_seller = '7'
ORDER BY o.amount DESC
If I separate the subquery from the main query, both return the data I expect and it seems strange to me the JOIN between the two does not work properly
I think the only real error is using curly braces instead of parentheses:
SELECT a.id, a.surname, a.name, o.amount
FROM levels l JOIN
anag a
ON a.phone = l.client_phone JOIN
(SELECT id_client, SUM(price) AS amount
FROM orders
WHERE id_seller = '7' AND status IN ('2', '3'))
GROUP BY id_client
) o
ON o.id_client = a.id
WHERE l.id_seller = '7'
ORDER BY o.amount DESC;
In addition:
You can use IN to shorten an equality comparison to multiple values.
Although I left them in, status and id_seller look like numbers. If so, drop the single quotes. Don't mix data types.
Your question is ambiguous on what to do if the seller in orders differs from the seller in anag for a customer. This keeps your logic (the sellers need to match).
SELECT a.id, a.surname, a.name, sum(o.price) 'amount'
FROM anag a
LEFT JOIN levels l ON l.id =a.id
LEFT JOIN orders of ON o.id_seller = l.id_seller AND o.id_client = l.id
GROUP BY o.id_seller
ORDER BY amount DESC
1. Problem Statement
I am having a difficultly to display the total of COUNT() at the correct row of record.
How do I display the COUNT() to the correct respective service which is
2. Background
I want to display the output of showing the total of the project in charge by staff based on the stage_id and breakdown into project_name.
What I have attemped / tried
SELECT
B.employee_name,
B.project_name,
A.total
FROM
(
SELECT
COUNT( * ) AS total,
services.NAME AS project_name,
services.id AS service_id,
users.id AS member_id,
users.NAME AS member_name
FROM
users
LEFT JOIN projects ON users.id = projects.leader_id
LEFT JOIN services ON projects.service_id = services.id
WHERE
( projects.service_id IN ( 1, 5 ) AND projects.stage_id < 6 )
OR ( projects.service_id IN ( 2, 3, 4, 7 ) AND projects.stage_id < 7 )
GROUP BY
member_name,
service_id
) AS A
RIGHT OUTER JOIN (
SELECT
users.id AS user_id,
users.NAME AS employee_name,
services.NAME AS project_name,
services.id AS service_id
FROM
users,
services
) AS B ON A.service_id = B.user_id RIGHT OUTER JOIN ( SELECT users.id AS user_id, users.NAME AS user_name, services.NAME AS project_name, services.id AS service_id FROM users, services ) AS B ON A.service_id = B.user_id
I used this query to generate the output below
+-------+-------------------+------------------+-------------------+
| id | project_name | employee_name | total |
+-------+-------------------+------------------+-------------------+
| 1 | Projects A | Employee A | 2 |
| 2 | Projects B | Employee A | 2 |
| 3 | Projects A | Employee B | 3 |
| 4 | Projects B | Employee B | 3 |
| 5 | Projects A | Employee C | 1 |
| 6 | Projects B | Employee C | 1 |
| 7 | Projects A | Employee D | 2 |
| 8 | Projects B | Employee D | 2 |
+-------+-------------------+------------------+-------------------+
The total of count assigns into the wrong row of record.
3. SQL Fiddle
This is the example of the output I have created on SQL Fiddle.
http://www.sqlfiddle.com/#!9/08eff4/1/0
4. Expected Output
I am expecting the total of count can be assigned to the correct row of record.
Output Expectation
+-------+-------------------+------------------+-------------------+
| id | project_name | employee_name | total | (COUNT (*) AS total)
+-------+-------------------+------------------+-------------------+
| 1 | Projects A | Employee A | 2 |
| 2 | Projects B | Employee A | NULL |
| 3 | Projects A | Employee B | 3 |
| 4 | Projects B | Employee B | NULL |
| 5 | Projects A | Employee C | 1 |
| 6 | Projects B | Employee C | NULL |
| 7 | Projects A | Employee D | 2 |
| 8 | Projects B | Employee D | NULL |
+-------+-------------------+------------------+-------------------+
I have running out of idea to achieve the expected outcome.
Hence, I would like to seek for help from the experts in this forum.
P/S: The field name might be different from the above because I write the query in a different schema
I managed to find my answer after keep on trying.
SELECT
A.NAME,
B.NAME,
(
SELECT
COUNT( * )
FROM
projects
LEFT JOIN users ON users.id = projects.leader_id
WHERE
(
projects.service_id IN ( 1, 5 )
AND projects.stage_id < 6
AND users.id = A.id
AND projects.service_id = B.id
)
OR (
projects.service_id IN ( 2, 3, 4, 7 )
AND projects.stage_id < 7
AND users.id = A.id
AND projects.service_id = B.id
)
)
FROM
users AS A
CROSS JOIN services AS B
This is the query that output my expected result as below.
+-------+-------------------+------------------+-------------------+
| id | project_name | employee_name | total | (COUNT (*) AS total)
+-------+-------------------+------------------+-------------------+
| 1 | Projects A | Employee A | 2 |
| 2 | Projects B | Employee A | NULL |
| 3 | Projects A | Employee B | 3 |
| 4 | Projects B | Employee B | NULL |
| 5 | Projects A | Employee C | 1 |
| 6 | Projects B | Employee C | NULL |
| 7 | Projects A | Employee D | 2 |
| 8 | Projects B | Employee D | NULL |
+-------+-------------------+------------------+-------------------+
I have two tables, users and survey. I want query the table user and to join the table survey in a way that only the survey record with the lowest value is returned for each record in user table.
I want to avoid subqueries and temporary tables.
table users:
--------------
| uid | name |
--------------
| 1 | mike |
| 2 | john |
| 3 | bill |
--------------
table survey:
----------------------
| id | uid | value |
----------------------
| 1 | 3 | 9 |
| 2 | 3 | 5 |
| 3 | 1 | 3 |
| 4 | 1 | 7 |
| 5 | 1 | 2 |
| 6 | 2 | 4 |
| 7 | 2 | 9 |
| 8 | 1 | 0 |
| 9 | 2 | 5 |
---------------------
expected output:
---------------------
| id | name | value |
---------------------
| 8 | mike | 0 |
| 2 | bill | 5 |
| 6 | john | 4 |
---------------------
What kind of JOIn should I do, or how should I write the query?
The following query gets all rows with minimum value (doesn't exist another survey with value under the selected value)
Try this:
SELECT u.*, s.value
FROM survey s
JOIN users u
ON s.uid = u.uid
WHERE NOT EXISTS(
SELECT 'maximum'
FROM survey s2
WHERE s2.uid = s.uid
AND s2.value < s.value)
You could use something like this:
select s.id, u.name, y.min_value
from
(
select uid, min(value) as min_value
from survey
group by uid
) y
join survey s
on s.value = y.min_value
and s.uid = y.uid
join user u
on u.uid = y.uid
I think this will help you
SELECT * FROM SURVEY S
INNER JOIN USERS U
ON S.UID=U.UID
QUALIFY ROW_NUMBER() OVER (PARTITION BY S.UID ORDER BY S.VALUE1 ASC )=1;
Here is the case I have two tables tags and customers as the following structure
Tags Table
ID Name
1 Tag1
2 Tag2
Customers Table
ID Tag_ID Name
1 1 C1
2 2 C2
3 1 C3
I want a SQL statement to get the first 10 customers (alphabetically) for each tag? is it possible to be done in one query.
P.S the data in the tables are sample data not the actual data
Consider the following:
DROP TABLE IF EXISTS tags;
CREATE TABLE tags
(tag_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL
);
INSERT INTO tags VALUES
(1,'One'),
(2,'Two'),
(3,'Three'),
(4,'Four'),
(5,'Five'),
(6,'Six');
DROP TABLE IF EXISTS customers;
CREATE TABLE customers
(customer_id INT NOT NULL
,customer VARCHAR(12)
);
INSERT INTO customers VALUES
(1,'Dave'),
(2,'Ben'),
(3,'Charlie'),
(4,'Michael'),
(5,'Steve'),
(6,'Clive'),
(7,'Alice'),
(8,'Ken'),
(9,'Petra');
DROP TABLE IF EXISTS customer_tag;
CREATE TABLE customer_tag
(customer_id INT NOT NULL
,tag_ID INT NOT NULL
,PRIMARY KEY(customer_id,tag_id)
);
INSERT INTO customer_tag VALUES
(1,1),
(1,2),
(1,4),
(2,3),
(2,2),
(3,1),
(4,4),
(4,2),
(5,2),
(5,5),
(5,6),
(6,6);
The following query returns all customers associated with each tag, and their respective 'rank' when sorted alphabetically...
SELECT t.*, c1.*, COUNT(ct2.tag_id) rank
FROM tags t
JOIN customer_tag ct1
ON ct1.tag_id = t.tag_id
JOIN customers c1
ON c1.customer_id = ct1.customer_id
JOIN customer_tag ct2
ON ct2.tag_id = ct1.tag_id
JOIN customers c2
ON c2.customer_id = ct2.customer_id
AND c2.customer <= c1.customer
GROUP
BY t.tag_id, c1.customer_id
ORDER
BY t.tag_id,rank;
+--------+-------+-------------+----------+------+
| tag_id | name | customer_id | customer | rank |
+--------+-------+-------------+----------+------+
| 1 | One | 3 | Charlie | 1 |
| 1 | One | 1 | Dave | 2 |
| 2 | Two | 2 | Ben | 1 |
| 2 | Two | 1 | Dave | 2 |
| 2 | Two | 4 | Michael | 3 |
| 2 | Two | 5 | Steve | 4 |
| 3 | Three | 2 | Ben | 1 |
| 4 | Four | 1 | Dave | 1 |
| 4 | Four | 4 | Michael | 2 |
| 5 | Five | 5 | Steve | 1 |
| 6 | Six | 6 | Clive | 1 |
| 6 | Six | 5 | Steve | 2 |
+--------+-------+-------------+----------+------+
If we just want the top 2, say, for each tag, we can rewrite that as follows...
SELECT t.*
, c1.*
FROM tags t
JOIN customer_tag ct1
ON ct1.tag_id = t.tag_id
JOIN customers c1
ON c1.customer_id = ct1.customer_id
JOIN customer_tag ct2
ON ct2.tag_id = ct1.tag_id
JOIN customers c2
ON c2.customer_id = ct2.customer_id
AND c2.customer <= c1.customer
GROUP
BY t.tag_id, c1.customer_id
HAVING COUNT(ct2.tag_id) <=2
ORDER
BY t.tag_id, c1.customer;
+--------+-------+-------------+----------+
| tag_id | name | customer_id | customer |
+--------+-------+-------------+----------+
| 1 | One | 3 | Charlie |
| 1 | One | 1 | Dave |
| 2 | Two | 2 | Ben |
| 2 | Two | 1 | Dave |
| 3 | Three | 2 | Ben |
| 4 | Four | 1 | Dave |
| 4 | Four | 4 | Michael |
| 5 | Five | 5 | Steve |
| 6 | Six | 6 | Clive |
| 6 | Six | 5 | Steve |
+--------+-------+-------------+----------+
This is fine, but where performance is an issue, a solution like the following will be faster - although you may need to run SET NAMES utf8; prior to constructing the tables (as I had to) in order for it to work properly:
SELECT tag_id, name, customer_id,customer
FROM
(
SELECT t.*
, c.*
, CASE WHEN #prev=t.tag_id THEN #i:=#i+1 ELSE #i:=1 END rank
, #prev := t.tag_id
FROM tags t
JOIN customer_tag ct
ON ct.tag_id = t.tag_id
JOIN customers c
ON c.customer_id = ct.customer_id
JOIN ( SELECT #i:=1, #prev:=0) vars
ORDER
BY t.tag_id
, c.customer
) x
WHERE rank <=2
ORDER
BY tag_id,customer;
+--------+-------+-------------+----------+
| tag_id | name | customer_id | customer |
+--------+-------+-------------+----------+
| 1 | One | 3 | Charlie |
| 1 | One | 1 | Dave |
| 2 | Two | 2 | Ben |
| 2 | Two | 1 | Dave |
| 3 | Three | 2 | Ben |
| 4 | Four | 1 | Dave |
| 4 | Four | 4 | Michael |
| 5 | Five | 5 | Steve |
| 6 | Six | 6 | Clive |
| 6 | Six | 5 | Steve |
+--------+-------+-------------+----------+
To achieve this, we have to use two session variables, one for the row number and the other for storing the old customer ID to compare it with the current one as the following query:
select c.name, #row_number:=CASE
WHEN #cid = c.id THEN #row_number + 1
ELSE 1
END AS rows,
#id:=c.id as CustomerId from tags t, customers c where t.id=c.id group by c.name where Rows<=10
We used CASE statement in the query. If the customer number remains the same, we increase the row_number variable
Reference
Your question reminds me of this one (see especially the top-voted answer), so I came up with this query:
SELECT Tags.ID,
Tags.Name,
SUBSTRING_INDEX(GROUP_CONCAT(Customers.Name
ORDER BY Customers.Name),
',', 10) AS Customers
FROM Customers
INNER JOIN Tags
ON Tags.ID = Customers.Tag_ID
GROUP BY Tags.ID
ORDER BY Tags.Id;
It works, but this is clearly a hacky way to do this, because MySQL does not offer yet tools to do this more naturally.
I need to get emtpy fields where data is repeated
For example an customer can have two or more contact persons, so query return (just shorted qyery resul):
CUSTOMER_NAME| CONTACT_PERSON|ETC..
dell | Ighor |etc..
dell | Dima |etc..
but I'm need :
CUSTOMER_NAME| CONTACT_PERSON|etc...
dell | Ighor |etc..
NULL | Dima |etc..
SELECT
`contact`.*,
`branch_has_equipment`.*,
`branch_has_contact`.*,
`equipment`.*,
`customer_has_branch`.*,
`branch`.*,
`customer`.*,
`ip`.*
FROM `customer`
INNER JOIN `customer_has_branch`
ON `customer`.`customer_id` = `customer_has_branch`.`customer_id`
INNER JOIN `branch`
ON `customer_has_branch`.`branch_id` = `branch`.`branch_id`
INNER JOIN `branch_has_equipment`
ON `branch`.`branch_id` = `branch_has_equipment`.`branch_id`
INNER JOIN `equipment`
ON `branch_has_equipment`.`equipment_id` = `equipment`.`equipment_id`
INNER JOIN `branch_has_contact`
ON `branch`.`branch_id` = `branch_has_contact`.`branch_id`
INNER JOIN `contact`
ON `branch_has_contact`.`contact_id` = `contact`.`contact_id`
INNER JOIN `equipment_has_ip`
ON `equipment`.`equipment_id` = `equipment_has_ip`.`equipment_id`
INNER JOIN `ip`
ON `equipment_has_ip`.`equipment_id` = `ip`.`ip_id`
WHERE `customer`.`inservice` = 'Yes'
ORDER BY `customer`.`customer_name`
in additional, tables ^
Customer
customer_id
customer_name
inservice
service_type
comment
Branch
branch_id
city
address
Equipment
equipment_id
brand
model
connection_param
connection_type
serial_number
id
release
Contact
contact_id
name
surname
phone_mobile
phone_work
phone_other
position
customer_has_branch_id
customer_id
branch_id
Since I have no idea how any of those tables relate to one another, my only answer to you is to use an OUTER JOIN, which will keep NULL results.
I'm not seriously advocating this solution because really i think this sort of thing should be handled in application level code (e.g. a bit of PHP), but anyway, consider the following:
SELECT * FROM my_table;
+------+--------+--------+
| game | points | player |
+------+--------+--------+
| 1 | 5 | Adam |
| 1 | 8 | Alan |
| 1 | 7 | Brian |
| 1 | 6 | John |
| 2 | 2 | Adam |
| 2 | 3 | Alan |
| 2 | 4 | Brian |
| 2 | 6 | John |
+------+--------+--------+
SELECT IF(game= #prev,'',game)
, #prev := game
FROM my_table ORDER BY game,player;
+-------------------------+---------------+
| IF(game= #prev,'',game) | #prev := game |
+-------------------------+---------------+
| 1 | 1 |
| | 1 |
| | 1 |
| | 1 |
| 2 | 2 |
| | 2 |
| | 2 |
| | 2 |
+-------------------------+---------------+