Grab unique data from repeating record - mysql

I've got a procedural question that is likely going to expose how burnt out I am. I have 3 tables, users, projects and project_users. projects is joined with project_user to allow users to share projects.
I'd like to let, say, Bob see all of his projects and who he is sharing them with. In the example below Bob's sharing his 1 project with everyone. In his dashboard I'd like to show him "Bob's 1 Project" with everyone it's shared with. This is being managed in a while loop because Bob really has dozens of projects he's sharing with dozen's of people. The problem is, how can I show 1 project with everyone it's shared_with instead of showing the same project over and over each time there's a new shared_with value?
id | users | | id | projects | | id | owner_id | shared_with | project_id | role
---+-------------------- ---+------------------- ---+----------+-------------+------------+------
1 | bob#here.com | | 1 | Bob's 1 Project | | 1 | 1 | NULL | 1 | 1
2 | tom#there.com | | 2 | Tom's | | 2 | 1 | 4 | 1 | 2
3 | jan#red.com | | 3 | Jan's | | 3 | 1 | 2 | 1 | 2
4 | joe#somewhere.com | | 4 | Joe's Project | | 4 | 1 | 3 | 1 | 2
5 | fred#where.com | | 5 | Fred's Project | | 5 | 1 | 5 | 1 | 2

Related

How to select every level with different user and user progress

I wanted to make a learning apps with a completed questions progress track on each level. I have 2 tables which contain all the level with its question count, and a table that save an user progress (completed questions) on each level. Here is the record,
Level table:
+----------+----------------------+-------------+--------+
| id_level | name | jumlah_soal | id_sub |
+----------+----------------------+-------------+--------+
| 1 | Basic Level 1 | 5 | 1 |
| 2 | Basic Level 2 | 6 | 1 |
| 3 | Basic Level 3 | 7 | 1 |
| 8 | Intermediate Level 1 | 5 | 2 |
| 9 | Intermediate Level 2 | 5 | 2 |
| 10 | Intermediate Level 3 | 5 | 2 |
..........................................................
Progress Table:
+-----------------+---------+-------------+----------+
| id_progreslevel | id_user | completed | id_level |
+-----------------+---------+-------------+----------+
| 1 | 1 | 2 | 1 |
| 2 | 1 | 3 | 2 |
| 3 | 2 | 2 | 1 |
+-----------------+---------+-------------+----------+
and when I joined the tables with the following query
SELECT IFNULL(progreslevel.id_user, 1) as id_user,
-> level.*, IFNULL(progreslevel.completed, 0) as completedquestions
-> FROM level LEFT JOIN progreslevel
-> ON level.id_level = progreslevel.id_level
-> WHERE level.id_sub = 1
-> HAVING id_user = 1;
It queries what I wanted:
+---------+----------+---------------+-------------+--------+--------------------+
| id_user | id_level | name | jumlah_soal | id_sub | completed questions |
+---------+----------+---------------+-------------+--------+--------------------+
| 1 | 1 | Basic Level 1 | 5 | 1 | 2 |
| 1 | 2 | Basic Level 2 | 6 | 1 | 3 |
| 1 | 3 | Basic Level 3 | 7 | 1 | 0 |
+---------+----------+---------------+-------------+--------+--------------------+
BUT, when I tried to change to query a progress for user ID = 2, it became like this:
+---------+----------+---------------+-------------+--------+--------------------+
| id_user | id_level | name | jumlah_soal | id_sub | completed questions |
+---------+----------+---------------+-------------+--------+--------------------+
| 2 | 1 | Basic Level 1 | 5 | 1 | 2 |
| 2 | 3 | Basic Level 3 | 7 | 1 | 0 |
+---------+----------+---------------+-------------+--------+--------------------+
Yes, the Basic Level 2 is gone because user 2 hadn't done it yet but user 1 had.
This is where I'm stuck, I want to whichever user I choose, its always query all the level, even when the other user had done it. It should be like this:
+---------+----------+---------------+-------------+--------+--------------------+
| id_user | id_level | name | jumlah_soal | id_sub | completed questions |
+---------+----------+---------------+-------------+--------+--------------------+
| 2 | 1 | Basic Level 1 | 5 | 1 | 2 |
| 2 | 2 | Basic Level 2 | 6 | 1 | 0 |
| 2 | 3 | Basic Level 3 | 7 | 1 | 0 |
+---------+----------+---------------+-------------+--------+--------------------+
How do I achieve this?
Thanks in advance and Sorry if you got dizzy either at my explanation or database, I tried my best to translate it, so it's understandable
I'm not really sure that I understand the requirement, but I think you're after something like this...
SELECT l.*
, 2 id_user
, COALESCE(MAX(p.completed),0) completed_questions
FROM level l
LEFT
JOIN progress p
ON p.id_level = l.id_level
AND p.id_user = 2
WHERE l.id_sub = 1
GROUP
BY l.id_level;

Whats the best way to store different prices for one entity in SQL?

So I am building a webpage that shows a bunch of video games located in a SQL database and one suggestion I had was to have the different prices from each region display based on a drop down. My question is trying to figure out whats the best way to store int in the database. Would it be like:
GAME
CountryID
price1
CountryID
price2
CountryID
price3 ...
Or is there a better way to do this?
Just a heads up I've only been developing web applications for a year or so and I'm still pretty new to SQL.
Thanks for your input!
I would use multiple tables, one for games and one for region pricing.
Games
+--------+----------+
| GameID | GameName |
+--------+----------+
| 1 | Game1 |
| 2 | Game2 |
| 3 | Game3 |
| 4 | Game4 |
+--------+----------+
RegionPricing
+----------+--------+-------+
| RegionID | GameID | Price |
+----------+--------+-------+
| 1 | 1 | 60 |
| 1 | 2 | 55 |
| 1 | 3 | 45 |
| 1 | 4 | 80 |
| 2 | 1 | 50 |
| 3 | 2 | 30 |
| 3 | 3 | 25 |
| 3 | 4 | 45 |
| 4 | 1 | 60 |
| 4 | 2 | 55 |
| 4 | 3 | 45 |
| 4 | 4 | 80 |
+----------+--------+-------+
By using separate tables you minimize duplicate data and allow for easy granular changes. You may also consider adding a column to RegionPricing for currency. This would also need a Region table, with RegionID and RegionName.

Conditionally move MySQL data between rows in same table

Working in Redmine, I need to copy(not move) data from certain rows to other rows based on matching project id numbers with time entries.
I have included a diagram of the table "custom_values" and my understanding of the design below(CURRENT DATA):
+----+-----------------+---------------+-----------------+-------+
| id | customized_type | customized_id | custom_field_id | value |
+----+-----------------+---------------+-----------------+-------+
| 1 | Project | 1 | 1 | 01 |
| 2 | TimeEntry | 1 | 4 | 01 |
| 3 | Project | 2 | 1 | 02 |
| 4 | TimeEntry | 2 | 4 | 02 |
| 5 | Project | 3 | 1 | 03 |
| 6 | TimeEntry | 3 | 4 | |
| 7 | Project | 4 | 1 | 04 |
| 8 | TimeEntry | 4 | 4 | |
+----+-----------------+---------------+-----------------+-------+
At the risk of oversimplifying,
"id" = The primary key for each entry in custom_values
"customized_type" = Specifies which db table the row is referring to.
"customized_id" = Specifies the primary key for the db table entry previously specified in "customized_type".
"custom_field_id" = Specifies which custom field the row is referring to. Redmine admins can arbitrarily add and remove custom fields.
"value" = The data contained within the custom field specified by
"custom_field_id"
In my situation, the values listed in "value" are representing unique customer id numbers. The customer id numbers did not always get entered with each time entry. I need to copy the customer numbers from the project rows to the matching time entry rows. Each time entry has a project_id field.
So far, here is my mangled SQL query:
SELECT
custom_field_id,
custom_values.value AS 'CUSTOMER_NUMBER',
custom_values.customized_id AS 'PROJECT_ID_NUMBER',
custom_values.customized_type,
time_entries.comments AS 'TIME_ENTRY_COMMENTS'
FROM
redmine_tweaking.custom_values
LEFT JOIN
redmine_tweaking.time_entries ON custom_values.customized_id = time_entries.project_id
WHERE
custom_values.customized_type='Project' AND custom_values.custom_field_id=1;
The query I have so far allows me to see that I have the time entries connected properly to their matching projects, but that is all I have been able to figure out. So in other words, this SQL statement does not exactly solve my problem.
Plus, even if it did work, I think the way I laid it out looks like 200 lbs of bird poop. There must be a better/more optimized way to do this.
Any help would be greatly appreciated. I am relatively new and I have been pouring hours into solving this problem.
UPDATE:
Ok, here is the time_entries table:
+----+------------+---------+----------+-------+----------+-------------+------------+-------+--------+-------+---------------------+---------------------+
| id | project_id | user_id | issue_id | hours | comments | activity_id | spent_on | tyear | tmonth | tweek | created_on | updated_on |
+----+------------+---------+----------+-------+----------+-------------+------------+-------+--------+-------+---------------------+---------------------+
| 1 | 1 | 1 | 1 | .25 | test | 9 | 2015-11-04 | 2015 | 11 | 45 | 2015-11-04 08:18:12 | 2015-11-04 10:18:12 |
| 2 | 2 | 1 | 1 | .25 | test2 | 9 | 2015-11-04 | 2015 | 11 | 45 | 2015-11-04 09:18:12 | 2015-11-04 12:18:12 |
+----+------------+---------+----------+-------+----------+-------------+------------+-------+--------+-------+---------------------+---------------------+
As opposed to the original table that I first posted, the expected output would show this:
+----+-----------------+---------------+-----------------+-------+
| id | customized_type | customized_id | custom_field_id | value |
+----+-----------------+---------------+-----------------+-------+
| 1 | Project | 1 | 1 | 01 |
| 2 | TimeEntry | 1 | 4 | 01 |
| 3 | Project | 2 | 1 | 02 |
| 4 | TimeEntry | 2 | 4 | 02 |
| 5 | Project | 3 | 1 | 03 |
| 6 | TimeEntry | 3 | 4 | 03 |
| 7 | Project | 4 | 1 | 04 |
| 8 | TimeEntry | 4 | 4 | 04 |
+----+-----------------+---------------+-----------------+-------+

Complex SQL Counting Query

I have a Facility Booking System and I would like to create a CSV format report.
1. I want to count total booking records
2. I want to count how many user booked our facilities, based on that timeslot
3. I want to combine two queries into one as I need to put the result into the CSV
And here is the table structure:
fbid | memberid | fbdate | fbtimeslot | fname | fposition | fattendance
------------------------------------------------------------------------------
1 | C00001 | 2014-12-12 | 1 | computer | 1 | 1
2 | C00002 | 2014-12-12 | 1 | computer | 4 | 3
3 | C00003 | 2014-12-12 | 1 | computer | 6 | 1
4 | C00002 | 2014-12-12 | 1 | computer | 8 | 3
5 | C00004 | 2014-12-12 | 1 | computer | 4 | 0
6 | C00002 | 2014-12-12 | 1 | computer | 24 | 1
7 | C00001 | 2014-12-12 | 2 | computer | 1 | 0
8 | C00002 | 2014-12-12 | 3 | computer | 1 | 0
For task 1, I have found the solution:
(fattendance = 3 means the position has changed and I have to keep record but the CSV report doesn't this)
SELECT fbtimeslot, COUNT(*) FROM facilitybooking WHERE fname='computer' AND fattendance<>3 GROUP BY fbtimeslot
But for 2 and 3, I tried more than 20 different statements but I still couldn't get the result.
Well, hard tasks though.
I will be very appreciated if you can help me to solve this.
Extras: SQLFiddle Link: http://sqlfiddle.com/#!2/4800b8/3

retrieving information from 3 tables

I have three tables:
users:
+----------+-----------------------------+-----------+
| users_id | user detail | otherID |
+----------+-----------------------------+-----------+
| 1 | user name or details | 1 |
| 2 | user name or details | 1 |
| 3 | user name or details | 4 |
| 4 | user name or details | 1 |
| 5 | user name or details | 21 |
| 6 | user name or details | 2 |
+----------+-----------------------------+-----------+
photos:
+----------+----------------+-----------+--------+---------+--------------+
| photosID | url | title | userID | likes | remarksID |
+----------+----------------+-----------+--------+---------+--------------+
| 1 | 7459.JPG | TITLE | 1 | 150 | 255 |
| 2 | 7510.JPG | TITLE | 1 | 146 | 247 |
| 3 | 7460.JPG | TITLE | 2 | 2 | 56 |
+----------+----------------+-----------+--------+---------+--------------+
remarks:
+-----------+---------------------------------------+---------+------------+
| remarksID | remark | userID | photoID |
+-----------+---------------------------------------+---------+------------+
| 1 | REMARKS for PhotoID 1 | 1 | 1 |
| 2 | REMARKS for PhotoID 1 | 1 | 1 |
| 3 | REMARKS for PhotoID 1 | 1 | 1 |
| 4 | REMARKS for PhotoID 2 | 1 | 2 |
| 5 | REMARKS for PhotoID 2 | 1 | 2 |
| 6 | REMARKS for PhotoID 3 | 2 | 3 |
+-----------+---------------------------------------+---------+------------+
I am trying to extract the remarks for a given users photo, but only want the photo to appear once but all the relevant remarks for the photo to be displayed for each users photo.
If there are no remarks then just display the photo without remarks.
The layout would look like this on a web page-
------------------------------------
Photograph 1
Remarks 1
Remarks 2
Remarks 1
------------------------------------
Photograph 2
NO remarks for photo
------------------------------------
Photograph 3
Remarks 1
Remarks 2
Remarks 3
Remarks 4
------------------------------------
Photograph 4
Remarks 1
Remarks 2
------------------------------------
Is my assumption correct that your difficulty is, how to get the database to do this? If so, then the answer is that this function (formatting the data), is not (or should not) generally be the responsibility of the database. Fetch the photos from the database as one result set, then fetch the matching comments in another, and let your application or reporting tool format the data the way you want it.