Access 2016 crosstab / transform - ms-access

I have table and I need to transform it at horizontal mode
| id | Number | Name |
|------|------------|--------|
| 3695 | 0445458225 | Name1 |
| 3695 | 0445458228 | Name2 |
| 3695 | 0445458553 | Name3 |
| 3695 | 0445458560 | Name4 |
| 3695 | 0445458551 | Name5 |
| 3695 | 0445458561 | Name7 |
| 3695 | 0445458522 | Name8 |
| 3695 | 0445458543 | Name9 |
| 3696 | 0445458226 | Name10 |
| 3696 | 0445458540 | Name11 |
| 3696 | 0445458543 | Name12 |
| 3696 | 0445923962 | Name13 |
| 3696 | 0500266382 | Name14 |
| 3697 | 0445923962 | Name15 |
| 3697 | 0445458226 | Name16 |
| 3697 | 0500266382 | Name17 |
| 3697 | 0445458564 | Name18 |
I got it as below:
| id | Name1 | Name2 | Name3 | Name4 | Name5 | Name6 | Name7 | Name8 | Name9 | Name10 | Name11 | Name12 | Name13 |
|------ |-----------|---------- |-------|----------|----------- |-------|-------|-------|----------|--------|---------- |----------|----------|
| 3695 | 445458553 | 44518551 | | 44548560 | | | | | 44548228 | | 44548543 | | 44548225 |
| 3696 | | | | | 445923962 | | | | | | 44548543 | 44548226 | |
| 3694 | | | | | 445923962 | | | | | | 44548543 | 44548226 | |
But what I need is this:
| id | Member1 | Member2 | Member3 | Member4 | Member5 | Member6 | Member7 | Member8 | Member9 | Member10 | member11 | Name12 | Name13 |
|------|-----------|----------|----------|----------|----------|----------|---------|---------|---------|----------|----------|--------|--------|
| 3695 | 445458553 | 44518551 | 44548560 | 44548228 | 44548543 | 44548225 | | | | | | | |
| 3696 | 445923962 | 44548543 | 44548226 | | | | | | | | | | |
| 3694 | 445923962 | 44548543 | 44548226 | | | | | | | | | | |
So no empty cells, column should be named as last table also original id, numbers and names are different
every time when query runs (different group id's)
Here is my SQL-code:
TRANSFORM Avg(Nick_agents.Number) AS FirstOfNumber
SELECT Nick_agents.id
FROM Nick_agents
GROUP BY Nick_agents.id
PIVOT Nick_agents.Name;

Access has a built-in Crosstab Query Wizard that does this for you.
On the Create tab, in the Queries group, click Query Wizard.
The Queries group in the Access ribbon displays two options: Query Wizard and Query Design
In the New Query dialog box, click Crosstab Query Wizard, and then click OK.
The Crosstab Query Wizard starts.
On the first page of the wizard, choose the table or query that you want to use to create a crosstab query. For this example, select the Products table and then click Next.
[![enter image description here][2]][2]
On the next page, choose the field that contains the values that you want to use as row headings. You can select up to three fields to use as row headings sources, but the fewer row headings you use, the easier your crosstab datasheet will be to read. If you choose more than one field to supply row headings, the order in which you choose the fields determines the default order in which your results are sorted.
For this example, select Supplier IDs.Value and then click the button labeled with a > symbol. Notice that Access displays the field name along the left side of the sample query preview at the bottom of the dialog box. Click Next to continue.
Select a field to display as row headings on the Crosstab query wizard.
On the next page, choose the field that contains the values that you want to use as column headings. In general, you should choose a field that contains few values, to help keep your results easy to read. For example, using a field that has only a few possible values (such as gender) might be preferable to using a field that can contain many different values (such as age).
If the field that you choose to use for column headings has the Date/Time data type, the wizard adds a step that lets you specify how to group the dates into intervals, such as months or quarters.
For this example, select Category and notice that Access displays category sample names along the top of the sample query preview at the bottom of the dialog box. Click Next to continue.
Select a field to display as row headings on the Crosstab query wizard.
If you choose a Date/Time field for column headings, the next page of the wizard asks you to specify the interval to use to group the dates. You can specify Year, Quarter, Month, Date, or Date/Time. If you do not choose a Date/Time field for column headings, the wizard skips this page.
On the next page, choose a field and a function to use to calculate summary values. The data type of the field that you select determines which functions are available.
On the same page, select or clear the Yes, include row sums check box to include or exclude row sums.
If you include row sums, the crosstab query has an additional row heading that uses the same field and function as the field value. Including a row sum inserts an additional column that summarizes the remaining columns. For example, if your crosstab query calculates average age by location and gender (with gender column headings), the additional column calculates the average age by location, across all genders.
For this example, select ID in the Fields box and Count in the Functions box in order to have Access count the number of products in each intersection of supplier and category. Leave the Yes, include row sums check box selected. Access will create a column that totals the number of products from each supplier. Click Next to continue.
Select a field and function to calculate on the Crosstab query wizard.
On the last page of the wizard, type a name for your query and then specify whether you want to view the results or modify the query design.
You can change the function that is used to produce row sums by editing the crosstab query in Design view.
If you've walked through this example using the Products table from the Northwind database, the crosstab query displays the list of supplier names as rows, the product category names as columns, and a count of the number of products in each intersection.
In your example, your data is completely different. In the first example, you have Name1, Name2, Name3, as field names and in the second example, you have Member1, Member2, Member3 as field names. Let's say this is your actual data.
id Number Name
3697 445923962 Member1
3696 445923962 Member1
3695 445458553 Member1
3696 445458543 Member2
3697 445458543 Member2
3695 445458543 Member2
3695 445458551 Member2
3695 445458560 Member3
3696 445458226 Member3
3697 445458226 Member3
Then, this is your SQL.
TRANSFORM First(Table1.[Number]) AS FirstOfNumber
SELECT Table1.[id], First(Table1.[Number]) AS [Total Of Number]
FROM Table1
GROUP BY Table1.[id]
PIVOT Table1.[Name];
This is the Design View.
When you run the SQL, you get this.
Make sense???

Related

How can I merge two strings of comma-separated numbers in MySQL?

For example, there are three rooms.
1|gold_room|1,2,3
2|silver_room|1,2,3
3|brown_room|2,4,6
4|brown_room|3
5|gold_room|4,5,6
Then, I'd like to get
gold_room|1,2,3,4,5,6
brown_room|2,3,4,6
silver_room|1,2,3
How can I achieve this?
I've tried: select * from room group by name; And it only prints the first row. And I know CONCAT() can combine two string values.
Please use below query,
select col2, GROUP_CONCAT(col3) from data group by col2;
Below is the Test case,
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=ab35e8d66ffe3ac6436c17faf97ee9af
I'm not making an assumption that the lists don't have elements in common on separate rows.
First create a table of integers.
mysql> create table n (n int primary key);
mysql> insert into n values (1),(2),(3),(4),(5),(6);
You can join this to your rooms table using the FIND_IN_SET() function. Note that this cannot be optimized. It will execute N full table scans. But it does create an interim set of rows.
mysql> select * from n inner join rooms on find_in_set(n.n, rooms.csv) order by rooms.room, n.n;
+---+----+-------------+-------+
| n | id | room | csv |
+---+----+-------------+-------+
| 2 | 3 | brown_room | 2,4,6 |
| 3 | 4 | brown_room | 3 |
| 4 | 3 | brown_room | 2,4,6 |
| 6 | 3 | brown_room | 2,4,6 |
| 1 | 1 | gold_room | 1,2,3 |
| 2 | 1 | gold_room | 1,2,3 |
| 3 | 1 | gold_room | 1,2,3 |
| 4 | 5 | gold_room | 4,5,6 |
| 5 | 5 | gold_room | 4,5,6 |
| 6 | 5 | gold_room | 4,5,6 |
| 1 | 2 | silver_room | 1,2,3 |
| 2 | 2 | silver_room | 1,2,3 |
| 3 | 2 | silver_room | 1,2,3 |
+---+----+-------------+-------+
Use GROUP BY to reduce these rows to one row per room. Use GROUP_CONCAT() to put the integers together into a comma-separated list.
mysql> select room, group_concat(distinct n.n order by n.n) as csv
from n inner join rooms on find_in_set(n.n, rooms.csv) group by rooms.room
+-------------+-------------+
| room | csv |
+-------------+-------------+
| brown_room | 2,3,4,6 |
| gold_room | 1,2,3,4,5,6 |
| silver_room | 1,2,3 |
+-------------+-------------+
I think this is a lot of work, and impossible to optimize. I don't recommend it.
The problem is that you are storing comma-separated lists of numbers, and then you want to query it as if the elements in the list are discrete values. This is a problem for SQL.
It would be much better if you did not store your numbers in a comma-separated list. Store multiple rows per room, with one number per row. You can run a wider variety of queries if you do this, and it will be more flexible.
For example, the query you asked about, to produce a result with numbers in a comma-separated list is more simple, and you don't need the extra n table:
select room, group_concat(n order by n) as csv from rooms group by room
See also my answer to Is storing a delimited list in a database column really that bad?

MySQL - Interchange column value from one row onto another

SELECT OlineDate, OlineOrder, OlineDesc, OlineGroup, OlinePrice
FROM tblorderlines
WHERE DATE(OlineDate) = '2019-10-19' AND OlineOrder = 170
AND OlineGroup IN ('spec')
|====================================================================|
| OlineOrder |OlineDate | OlineDesc | OlineGroup | OlinePrice |
|============+============+===========+================+=============|
| 10 | 2019-10-19 | Coupon | spec | -2.42 |
|------------+------------+-----------+----------------|-------------|
| 10 | 2019-10-19 | 10% OFF | spec | 0.00 |
|------------+------------------------+----------------+-------------|
I am looking for a query that would interchange the '10% off' value over the 'Coupon' value. The only results I've found that may produce the result I want are pivot tables but those don't exist in MySQL. Is there another route I can take?

Merge duplicate (row group) column cells

ID| Date1 | Date 2 |Total
-----------------------------------
1 | 15/02/2017 |02/02/2017 | 3 |
-----------------------------------
1 | 15/02/2017 |05/08/2017 | 3 |
-----------------------------------
1 | 15/02/2017 |12/12/2017 | 3 |
-----------------------------------
2 | 12/05/2017 |07/08/2017 | 2 |
-----------------------------------
2 | 12/05/2017 |10/08/2017 | 2 |
I have a table that is displaying data like above. I'm grouping that data on "ID" column. Values for Columns "Date1" & "Total" for a particular "ID" are the same but "Date2" value can be different in a given group.
How can i merge the cells across rows when the values are the same such that it displays like below?
ID| Date1 | Date 2 |Total
-----------------------------------
1 | 15/02/2017 |02/02/2017 | 3 |
--| |------------| |
1 | |05/08/2017 | |
--| |------------| |
1 | |12/12/2017 | |
---------------------------------|
2 | 12/05/2017 |07/08/2017 | 2 |
--| |------------| |
2 | |10/08/2017 | |
I did manage to find that "HideDuplicates" TextBox property, but while that will suppress the repetition of the cell values in adjacent rows it does not merge those duplicate cells down the column across rows
Its difficult to tell how the report is setup in terms of groups etc without seeing the design, but this is pretty simple to do from scratch.
Start with a simple table with just your detail rows, no grouping. Then right-click the detail row in the row group panel under the main report design area. Choose Add Group -> Parent Group
Choose your Date1 field in the group by drop down . Click OK and you're done.

How to make IN condition check for set values

Basically I have two tables
MY_CHARACTER:
_________________________________________________
| char_ID | char_name | char_class | char_rank |
|------------------------------------------------|
| 1 | Aragorn | Fighter | 99 |
| 2 | Legolas | Archer | 90 |
| 3 | Smeagle | Spy | 20 |
|________________________________________________|
and
EQUIPMENT:
_________________________________________________
| equip_ID | equip_name | equip_owner | required |
|--------------------------------------------------|
| 1 | The one ring | 3 | 99 |
| 2 | Longsword | 1 | 90 |
| 3 | Waistcloth | 3 | 10 |
| 4 | Nazguls Mask | 2 | 95 |
|__________________________________________________|
Now what I want is to make a select command using IN condition, which will give me list of equipments that the characters are not eligible to use. So in this very example, it would be Smeagle being ineligible to wear the one ring and Legolas unable to wield the nazguls mask.
My command looks something like this
SELECT equip_name, equip_owner, required
FROM EQUIPMENT WHERE required IN (SELECT char_rank MY_CHARACTER);
Now this will only print out the equipment where required=char_rank however i want to print out a select, where required equipment level is higher than char_rank instead. Any idea how? Ideally using the IN condition.
EDIT: To clear out confusion regarding where I want, basically what my command does right now is it checks if EQUIPMENT.required=MY_CHARACTER.char_rank what I want instead is that it checks EQUIPMENT.required>MY_CHARACTER.char_rank
I would do this with a join:
select c.*, equip_id as notEligible
from my_character c join
equipment e
on c.char_rank < e.required;
So if you want a list of items, that a certain character is not allowed to use you can slightly modify your SQL:
SELECT
equip_name, equip_owner, required
FROM
EQUIPMENT
WHERE
required > (SELECT char_rank FROM MY_CHARACTER WHERE char_id=?);

export mysql table with data spread over multiple rows to csv

I have a mysql table which is filled with inputs from a webform on my website. The form has fields for last name, surname, email, phone, address, etc.... and when a user submits the form these data are stored in a mysql table in a rather strange way.
my table looks like this:
subission# | value | field | tstamp | and |many |more |columns
=====================================================================================
1 |john#server.com |email |1448898875 | | | |
1 |john |firstname|1448898875 | | | |
1 |doe |lastname |1448898875 | | | |
1 |london |city |1448898875 | | | |
2 |jane#aol.com |email |1448898870 | | | |
2 |jane |firstname|1448898870 | | | |
2 |doe |lastname |1448898870 | | | |
2 |new york |city |1448898870 | | | |
3 |tim #aol.com |email |1448838571 | | | |
3 |tim |firstname|1448838571 | | | |
3 |smith |lastname |1448838571 | | | |
3 |paris |city |1448838571 | | | |
I need to export these data to a csv file in order to import it to a newsletter script on some other server, but the server expects these data in a different format:
submission#,email,firstname,lastname,tstamp,.....
1,john#server.com,john,doe,london,1448898875,,,,
2,jane#aol.com,jane,doe,1448898870,,,,
The export as csv is not the problem, but how do I get all the data of one submission# into one row? Can anyone please point me into the right direction, how to accomplish this with SQL?
You can achieve the desired output, if you concatenate the field contents into a single field using concat() and group_concat() functions, where the values are separated by comma.
The only issue can be if for a particular submission any of the properies is missing. If that's the case, then you will need a helper table which lists all properies and you need to left join on that table. Since this is not the case for your sample data, I'm not providing the code for this scenario.
select concat(submission, ',', group_concat(`value` order by `field` asc), ',',tstamp)
from table group by submission, tstamp
If you need the field names in the 1st row, then create a separate query that conatenates the field names separated by commas and combine the 2 with union.