How to collapse MS Access Table rows by matching IDs - ms-access

I have a table similar to the Example Source Table shown below that I would like to collapse based on the ID field (see Example Collapsed Table). I can do this with code but it inflates my Access database beyound the 2 GB maximum size so I'm hoping there is a way to do it with a query. I should probably note that for any given ID value I don't need to worry about more than one record having a value in field One, Two, Three, or Four.
Example Source Table:
ID One Two Three Four
1 My Is
1 Matt
1 Name
2 My Is Matt
2 Name
3 My Name Is Matt
Example Collapsed Table:
ID One Two Three Four
1 My Name Is Matt
2 My Name Is Matt
3 My Name Is Matt

You can use an aggregate query which groups by ID and returns the Max() for each of those other 4 columns within each ID grouping.
SELECT
ID,
Max(One),
Max(Two),
Max(Three),
Max(Four)
FROM tblSource
GROUP BY ID;
If you want to store the results in a new table, convert the query to a "make table query". If you already have your destination table created and want to add those results to it, convert the query to an "append query".
If you're approaching the 2 GB db file size limit, first use Compact & Repair to discard unused space. If compact doesn't give you enough working room, create another db file and store the new (collapsed) table there. You can link to it from your original database.

Related

Using lookup transformation for 2 columns at the same time

I want to use lookup transformation for 2 columns at the same time in SSIS. For example, if there are 3 columns ProductID,CreatedDate,Pname I need to compare 2 columns say ProductID and CreatedDate at the same time so that only if a row has same ProductID but different Created Date it should go in no match output. Currently my transformation is just using productid and if its already exists, it is putting in matched rows even after having a different CreatedDate.
As per above example, both ProductID with 1 should be there in no match output.
How can we implement this in SSIS?
It's very simple. Currently I believe you have only source.ProducID mapped to destination.ProductID in lookup.
All you need to do is map source.CreatedDate to destination.CreatedDate.
You need to do something like this :

Efficient read and write in mysql database

I have a mysql table which stores a set of queries (strings).
The table with its contents looks like this :-
query_id queryString
1. Query 1
2. Query 2
3. Query 3
The results table which are somehow related to the above mentioned queries are stored in a different mysql table in the form shown
result_id query_id resultString
1. 1 Result 1
2. 1 Result 2
3. 2 Result 3
4. 2 Result 4
5. 2 Result 1
6. 3 Result 3
7. 3 Result 4
8. 3 Result 5
Clearly, the model above has redundancy, as I have to store Result 1 , Result 3 and Result 4 more than once. This redundancy further increases with increase in number of similar queries. So, lets say if I have to do some processing on the results query, I would have to do on several duplicate values.
In another alternative which I can think of is that I can store results uniquely in a table and store the results_id to which they refer along with the queries in the query table. But in that case, while reading results for a query, I would have to hit a number of mysql queries, one corresponding to every result_id that I have. So, that seems inefficient(w.r.t read) to me.
What other possible solutions could help me in removing redundancies with minimal increase in the read/write load ?
Please comment if I am unclear in asking my doubt.
Thanks !
It seems this is a N:N relationship between querys and resultstrings so :
You need for Querystrings like the one you already have.
Create another table for resultstrings and create another one to link querystrings and resultstrings. Dont forget foreign keys.

it is possible to "group by" without losing the original rows?

i have a query like this:
ID | name | commentsCount
1 | mysql for dummies | 33
2 | mysql beginners guide | 22
SELECT
...,
commentsCount // will return 33 for first row, 22 for second one
FROM
mycontents
WHERE
name LIKE "%mysql%"
also i want to know the total of comments, of all rows:
SELECT
...,
SUM(commentsCount) AS commentsCountAggregate // should return 55
FROM
mycontents
WHERE
name LIKE "%mysql%"
but this one obviously returns a single row with the total.
now i want to merge these two queries in one single only,
because my actual query is very heavy to execute (it uses boolean full text search, substring offset search, and sadly lot more), then i don't want to execute it twice
is there a way to get the total of comments without making the SELECT twice?
!! custom functions are welcome !!
also variable usage is welcome, i never used them...
You can cache the intermediate result to a temporary table, and then do the sum over this table
One obvious solution is storing intermediate results withing another 'temporary' table, and than perform aggregation in the second step.
Another solution is preparing a lookup table containing sums you need (but there obviously needs to be some grouping ID, I call it MASTER_ID), like that:
CREATE TABLE comm_lkp AS
SELECT MASTER_ID, SUM(commentsCount) as cnt
FROM mycontents
GROUP BY MASTER_ID
Also create an index on that table on column MASTER_ID. Later, you can modify your query like that:
SELECT
...,
commentsCount,
cnt as commentsSum
FROM
mycontents as a
JOIN comm_lkp as b ON (a.MASTER_ID=b.MASTER_ID)
WHERE
name LIKE "%mysql%"
It also shouldn't touch your performance as long as lookup table will be relatively small.
A GROUP BY on one of the ID fields might do the trick. This will then give you the SUM(commentsCount) for each ID.
The query in your question is not detailed enough to know which of your fields/tables the ID field should come form.

How can I add a "group" of rows and increment their "group id" in MySQL?

I have the following table my_table with primary key id set to AUTO_INCREMENT.
id group_id data_column
1 1 'data_1a'
2 2 'data_2a'
3 2 'data_2b'
I am stuck trying to build a query that will take an array of data, say ['data_3a', 'data_3b'], and appropriately increment the group_id to yield:
id group_id data_column
1 1 'data_1a'
2 2 'data_2a'
3 2 'data_2b'
4 3 'data_3a'
5 3 'data_3b'
I think it would be easy to do using a WITH clause, but this is not supported in MySQL. I am very new to SQL, so maybe I am organizing my data the wrong way? (A group is supposed to represent a group of files that were uploaded together via a form. Each row is a single file and the the data column stores its path).
The "Psuedo SQL" code I had in mind was:
INSERT INTO my_table (group_id, data_column)
VALUES ($NEXT_GROUP_ID, 'data_3a'), ($NEXT_GROUP_ID, 'data_3b')
LETTING $NEXT_GROUP_ID = (SELECT MAX(group_id) + 1 FROM my_table)
where the made up 'LETTING' clause would only evaluate once at the beginning of the query.
You can start a transaction do a select max(group_id)+1, and then do the inserts. Or even by locking the table so others can't change (insert) to it would be possible
I would rather have a seperate table for the groups if a group represents files which belong together, especially when you maybe want to save meta data about this group (like the uploading user, the date etc.). Otherwise (in this case) you would get redundant data (which is bad – most of the time).
Alternatively, MySQL does have something like variables. Check out http://dev.mysql.com/doc/refman/5.1/en/set-statement.html

Merge columns in MySQL SELECT

I have a table that stores a default configuration and a table that stores a user configuration. I can join the two tables and get all the info I need however I was hoping there might be a cleaner way to overwrite one column with the other when a value exists in the second column.
Example:
Current query result:
id defaultValue userValue
1 one ONE
2 two
3 three THREE
4 four
Desire query result:
id value
1 ONE
2 two
3 THREE
4 four
Maybe there isn't a good way to do this... Thought I'd ask though as it's probably faster to do it in MySQL if a method exists than to do it in PHP.
You can use COALESCE() for this:
SELECT id, COALESCE(uservalue,defaultvalue) AS value
FROM table