i want to change the format of the table that i had. i've heard about the pivot statement but don't know how to apply it to my situation.
i thought about rearrange the table once i export it to csv file but it will take time and an extra step.
this is what i have so far
+------+------------+-----------+-------+
| name | date | breakfast | lunch |
+------+------------+-----------+-------+
| Mike | 21/02/2019 | 1 | 0 |
| Adam | 21/02/2019 | 1 | 0 |
| Liam | 13/05/2019 | 1 | 1 |
+------+------------+-----------+-------+
i would like to change the format to
+------------+-----------+-------+
| days | breakfast | lunch |
+------------+-----------+-------+
| 21/02/2019 | | |
| Mike | 1 | 0 |
| Adam | 1 | 0 |
| 13/05/2019 | | |
| Liam | 1 | 1 |
+------------+-----------+-------+
it does not have to be exactly the same, i just want the export to show the name and meals based on date
i tried to use group by but i got it wrong, please help
Related
Let's say i have a user table like this :
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1#mail.com | 24 |
| 2 | Josh | josh99#mail.com | 29 |
| 3 | Joseph | joseph410#mail.com | 21 |
| 4 | George | gge.48#mail.com | 28 |
| 5 | Joseph | jh.city89#mail.com | 24 |
| 6 | Kim | kimsd#mail.com | 32 |
| 7 | Bob | bob.s#mail.com | 38 |
| 8 | Joseph | psa.jos#mail.com | 34 |
| 9 | Joseph | joseph.la#mail.com | 28 |
| 10 | Jonathan | jonhan#mail.com | 22 |
+----+-----------+---------+------------+------+
In the actual, the database consists of more data and some of the data is duplicated, with more than two records. But the point is i want to get only the first and the second row of the duplicated rows that contains the name of "Joseph", How can i achieve this ? My code so far...
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 1')->get();
With that code the result will retrieve :
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1#mail.com | 24 |
| 2 | Josh | josh99#mail.com | 29 |
| 3 | Joseph | joseph410#mail.com | 21 |
| 4 | George | gge.48#mail.com | 28 |
| 6 | Kim | kimsd#mail.com | 32 |
| 7 | Bob | bob.s#mail.com | 38 |
| 10 | Jonathan | jonhan#mail.com | 22 |
+----+-----------+---------+------------+------+
And i use this code to try to get the second duplicated row :
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 2')->get();
The result is still same as the mentioned above :
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1#mail.com | 24 |
| 2 | Josh | josh99#mail.com | 29 |
| 3 | Joseph | joseph410#mail.com | 21 |
| 4 | George | gge.48#mail.com | 28 |
| 6 | Kim | kimsd#mail.com | 32 |
| 7 | Bob | bob.s#mail.com | 38 |
| 10 | Jonathan | jonhan#mail.com | 22 |
+----+-----------+---------+------------+------+
I want the result is to get record that have the id "5" with name "Joseph" like this :
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 1 | John | john.doe1#mail.com | 24 |
| 2 | Josh | josh99#mail.com | 29 |
| 4 | George | gge.48#mail.com | 28 |
| 5 | Joseph | jh.city89#mail.com | 24 |
| 6 | Kim | kimsd#mail.com | 32 |
| 7 | Bob | bob.s#mail.com | 38 |
| 10 | Jonathan | jonhan#mail.com | 22 |
+----+-----------+---------+------------+------+
But it seems only the first duplicate row is retrieved and i can't get the second duplicated row, can anybody give me suggestion ?
Let's start from your query
User::withTrashed()->groupBy('name')->havingRaw('count("name") >= 1')->get();
This will show all groups of rows whose count equals to 1 ore more. and this is the description of DISTINCT.
If you want to get only duplicate records you should get groups whose count is LARGER than 1.
The other thing to notice here is that a non-aggrigated column will be chosen randomly. because when you get a name and it's count, for example if you select name,count(name), email (email is not in the group by clause - not aggregated), and 4 rows have the same name. so you'll see:
+--------+-------------+-------+
| Name | Count(Name) | Email |
+--------+-------------+-------+
| Joseph | 4 | X |
+--------+-------------+-------+
what do you expect instead of X? which one of the 4 emails? actually, in SQLServer it's forbidden to select a non-aggrigated column and other databases will just give you a random one of the counted 3.
see this answer for more details it's explained very well: Do all columns in a SELECT list have to appear in a GROUP BY clause
So, we'll use having count(name) > 1 and select only the aggregated column name
DB::from('users')->select('name')->groupBy('name')->havingRaw('count("name") > 1')->get();
This should give you (didn't test it) this:
+--------+-------------+
| name | Count(name) |
+--------+-------------+
| Joseph | 4 |
+--------+-------------+
This will give you all names who have 2 or more instances. you can determine the number of duplicates in the having clause. for example having count(name) = 3 will give you all names which have exactly 3 duplicates.
So how to get the second duplicate? I have a question for that:
What is the first (original) duplicate? is it the one with the oldest created_at or the oldest updated_at ? or maybe some other condition?. because of that you should make another query with order by clause to give you the duplicates in the order most convenient to you. for example:
select * from `users` where `name` in (select `name` from users group by `name` having count(`name`) > 1) order by `id` asc
which will give:
+----+-----------+----------------------+------+
| ID | Name | Email | Age |
+----+-----------+----------------------+------+
| 3 | Joseph | joseph410#mail.com | 21 |
| 5 | Joseph | jh.city89#mail.com | 24 |
| 8 | Joseph | psa.jos#mail.com | 34 |
| 9 | Joseph | joseph.la#mail.com | 28 |
+----+-----------+---------+------------+------+
I've got a table that looks like this:
+----+--------------------------------+
| id | slug |
+----+--------------------------------+
| 1 | gift |
| 1 | psychological-manipulation |
| 1 | christmas |
| 1 | giving |
| 1 | the-town-santa-forgot |
| 1 | santa-claus |
| 1 | mp3 |
| 1 | christmas |
| 2 | entertainment-culture |
| 2 | christmas |
| 2 | culture |
| 2 | literature |
| 2 | christmas-music |
| 2 | christmas-window |
| 2 | broadcasting-nec |
| 2 | how-the-grinch-stole-christmas |
| 2 | the-polar-express |
| 2 | banker |
| 2 | christmas |
| 2 | potter |
| 2 | christmas-eve |
| 2 | bailey |
| 2 | its-a-wonderful-life |
| 2 | the-polar-express |
| 2 | disney |
| 2 | tim-burton |
| 2 | a-christmas-carol |
| 2 | the-nightmare-before-christmas |
| 2 | chuck-jones |
+----+--------------------------------+
I want to get unique ids from the table where at least two of a list of slugs match for a given id.
For example lets say I've got the slugs values of:
gift
christmas
giving
I would want all unique ids that have a matching record for at least 2 of those.
i.e. only an id that had both the gift AND christmas slug or the giving AND christmas slug or the gift AND giving slug, etc...
You can use the distinct modifier to count the number of different slugs per ID:
SELECT id
FROM mytable
WHERE slug IN ('gift', 'christmass', 'giving')
GROUP BY id
HAVING COUNT(DISTINCT slug) >= 2
I have the following table:
TABLE sales
| id | name | date | amount |
|----|------|------------|--------|
| 1 | Mike | 2016-12-05 | 67.15 |
| 2 | Mike | 2016-12-09 | 98.24 |
| 3 | John | 2016-12-12 | 12.98 |
| 4 | Mike | 2016-12-19 | 78.48 |
| 5 | Will | 2016-12-19 | 175.26 |
| 6 | John | 2016-12-22 | 14.26 |
| 7 | John | 2016-12-23 | 13.48 |
I am trying to create a view that will group by the name column and return only the most resent amount. It should look like this:
TABLE sales_view
| id | name | date | amount |
|----|------|------------|--------|
| 4 | Mike | 2016-12-19 | 78.48 |
| 5 | Will | 2016-12-19 | 175.26 |
| 7 | John | 2016-12-23 | 13.48 |
I'm not sure how to go about making this. I would imagine I would need sub-queries, but I know that SQL get mad if you try to use them inside of views.
You can use a tuple and a subquery with group by for max(date)
select * from sales
where (name, date) in ( select name, max(date)
from sales
group by name)
I have an access table containing over 100,000 records. My problem is that many of the records have duplicate information. I would like to merge/combine the records into record.
I have a field (CommonField) that can be used to identify the duplicates (sometimes more than two records). Each field needs to be considered on an individual basis. For instance:
If the date fields are not equal, I would prefer to keep the most recent date.
If the count fields are not equal, I would prefer to keep the larger value.
If the company names are not equal, I would prefer to keep both names unless one is within the other.
CLICK HERE for a sample of the data:
+------------------+-------------+-------+-------+------------------+-----------+------------+--------+-----------------------------+
| Existing Records | | | | | | | | |
+------------------+-------------+-------+-------+------------------+-----------+------------+--------+-----------------------------+
| ID | CommonField | First | Last | Email | Date | Currency | Count | Company |
| 1 | AA123 | John | | | | $465,000 | | ABC Company Ltd |
| 2 | AA123 | John | | John#gmail.com | 1-Mar-78 | $465,000 | 87,000 | ABC Company |
| 3 | AA123 | | Doe | | 14-Mar-78 | $465,000 | 88,000 | |
| 4 | BB456 | Dave | Smith | | 1-Apr-92 | $1,200,000 | 5,000 | Carter Company |
| 5 | BB456 | | Smith | Dave#aol.com | 1-Apr-92 | $1,200,000 | 5,000 | Simpson Ltd |
| 6 | CC568 | | | Jane#hotmail.com | 1-Sep-05 | $60,000 | | Woods Holdings |
| 7 | CC568 | | Woods | Jane#hotmail.com | | | 40,000 | Woods |
| 8 | CC568 | Jane | Woods | | 1-Sep-05 | | | |
| 9 | DD211 | Bob | Burns | Bob#gmail.com | 5-Aug-01 | $678,100 | 21,400 | |
| | | | | | | | | |
| Desired Result | | | | | | | | |
| ID | CommonField | First | Last | Email | Date | Currency | Count | Company |
| 10 | AA123 | John | Doe | John#gmail.com | 14-Mar-78 | $465,000 | 88,000 | ABC Company Ltd |
| 11 | BB456 | Dave | Smith | Dave#aol.com | 1-Apr-92 | $1,200,000 | 5,000 | Carter Company, Simpson Ltd |
| 12 | CC568 | Jane | Woods | Jane#hotmail.com | 1-Sep-05 | $60,000 | 40,000 | Woods Holdings |
| 13 | DD211 | Bob | Burns | Bob#gmail.com | 5-Aug-01 | $678,100 | 21,400 | |
+------------------+-------------+-------+-------+------------------+-----------+------------+--------+-----------------------------+
I am interested in hearing your suggestions as to the best way of tackling this project.
Ugly.
I think for the name fields, you may need another table to combine names. I'd start by making a new table from a group by query on both the common id and the company name. Add an extra field for the standardized name to the table, then use a find duplicates query to look at all the common ids with more than one name and manually assign a standardized name.
Then you can bring both the original data table and the company names table into a group by query and pull the standardized name into the final result. For the data and count fields, you can use max(date) and max(count). This should work for the first, last and email text fields also - but you will want to manually examine the results pretty carefully.
I'm stuck with some tables in mysql. Don't really know how to join the info from three tables. Very thankful if anyone could help me. Thanks.
This is what I have:
Table1.Users
+----+--------+--------------+
| id | name | lastname |
+----+--------+--------------+
| 1 | Peter | Elk |
| 2 | Amy | Lee |
| 3 | James | Ride |
| 4 | Andrea | Thompson |
+----+--------+--------------+
Table2.Projects
+-----+-------------+
| id | name |
+-----+-------------+
| 13 | Lmental |
| 26 | Comunica |
| 28 | Ecobalear |
| 49 | Puigpunyent |
+-----+-------------+
Table3.Users_Projects
+----------+-------------+
| id_users | id_projects |
+----------+-------------+
| 1 | 13 |
| 1 | 28 |
| 2 | 13 |
| 2 | 28 |
| 2 | 49 |
| 3 | 28 |
| 3 | 49 |
| 4 | 49 |
+----------+-------------+
And I would like to print something like this:
+--------+--------------+----------------------------------+
| name | lastname | project |
+--------+--------------+----------------------------------+
| Peter | Elk | Lmental,Ecobalear |
| Amy | Lee | Lmental,Ecobalear, Puigpunyent |
| James | Ride | Ecobalear,Puigounyent |
| Andrea | Thompson | Puigpunyent |
+--------+--------------+----------------------------------+
Something like...
SELECT Users.name, Users.lastname, Projects.name
FROM (Users, Projects, Users_Projects)
WHERE Users_Projects.id_users=Users.id AND Users_Projects.id_projects=Projects.id
ORDER BY ...
...will output a single user/project per line, which you'll then have to manipulate in your choosen language.
Attempting to perform the concatenation, etc. in SQL is liable to lead to a pretty horrendous query.