I have a table that has
Material 90 89 88 87 ….2 1 0
123456 34 30 26 38 14 12 8
123457 47 42 33 54 38 27 42
And I want to convert it to
Date 123456 123457
Date()-90 34 47
Date()-89 30 42
Date()-88 26 33
Date()-87 38 54
…. ………… ………..
Date()-2 14 38
Date()-1 12 27
Date() 8 42
I found this, but am trying to figure out how to use it:
Private Sub Unpivot_Click()
Dim x As Integer
Dim columncount As Integer
Dim setRST As DAO.Recordset
Dim sqlstr As String
Dim qdf As DAO.QueryDef
Dim fld As DAO.Field
Set setRST = CurrentDb.OpenRecordset("Select * from TheTable")
columncount = setRST.Fields.Count
Set qdf = db.CreateQueryDef ("", "Insert Into TheDestination ([Template], [Row],
[Column], [Result]) VALUES (#Template, #RowNumber, #ColumnNumber, #Result)")
Do While Not setRST.EOF
qdf.Parameters("#Template") = setRST!Template
qdf.Parameters("#RowNumber") = setRST!row
For Each fld In setRST.Fields
If IsNumeric(fld.Name) Then
qdf.Parameters("#ColumnNumber") = fld.Name
qdf.Parameters("#Result") = fld.Value
qdf.Execute
End If
Next fld
setRST.MoveNext
Loop
End Sub
So far, I have:
Public Function Unpivot()
Dim x As Integer
Dim columncount As Integer
Dim setRST As DAO.Recordset
Dim sqlstr As String
Dim qdf As DAO.QueryDef
Dim fld As DAO.Field
Set setRST = CurrentDb.OpenRecordset("SSMaterialByDayQ322")
columncount = setRST.Fields.Count
Set qdf = db.CreateQueryDef("", "Insert INTO SSHistoryQ322 ([Date], [Row], [Column], [Result]) VALUES (#Template, #RowNumber, #ColumnNumber, #Result)")
Do While Not setRST.EOF
qdf.Parameters("#Template") = setRST!Date
qdf.Parameters("#RowNumber") = setRST!row
For Each fld In setRST.Fields
If IsNumeric(fld.Name) Then
qdf.Parameters("#ColumnNumber") = fld.Name
qdf.Parameters("#Result") = fld.Value
qdf.Execute
End If
Next fld
setRST.MoveNext
Loop
End Function
You can start by making a union query
SELECT 'Date()-90' As [Date], Material, [90] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-89' As [Date], Material, [89] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-88' As [Date], Material, [88] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-87' As [Date], Material, [87] As [Value] FROM TheTable
...
UNION ALL
SELECT 'Date()-02' As [Date], Material, [2] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-01' As [Date], Material, [1] As [Value] FROM TheTable
UNION ALL
SELECT 'Date()-00' As [Date], Material, [0] As [Value] FROM TheTable
Of course, you can use VBA to create this query in a loop. Store this SQL-Text as query qryFlatten.
Now we build a pivot query from this query. This yields our final result
TRANSFORM Sum(qryFlatten.Value) AS SumOfValue
SELECT qryFlatten.Date
FROM qryFlatten
GROUP BY qryFlatten.Date
ORDER BY qryFlatten.Date DESC
PIVOT qryFlatten.Material;
If there are not more than 50 fields in the table needing to be 'unpivoted', a UNION query can rearrange the data to a normalized structure. There is no query builder or wizard for UNION, must type or copy/paste in SQL view. UNION has limit of 50 SELECT lines.
SELECT "Date()-90" AS [Date], Material, [90] AS Data FROM SSMaterialByDayQ322
UNION SELECT "Date()-89", Material, [89] FROM SSMaterialByDayQ322
UNION SELECT "Date()-88", Material, [88] FROM SSMaterialByDayQ322
UNION SELECT "Date()-87", Material, [87] FROM SSMaterialByDayQ322
UNION SELECT "Date()-2", Material, [2] FROM SSMaterialByDayQ322
UNION SELECT "Date()-1", Material, [1] FROM SSMaterialByDayQ322
UNION SELECT "Date()-0", Material, [0] FROM SSMaterialByDayQ322;
If there are more than 50 year fields, VBA can write records to table, consider:
Public Sub Unpivot()
Dim x As Integer
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("SSMaterialByDayQ322")
Do While Not rst.EOF
For x = 1 To rst.Fields.Count - 1
CurrentDb.Execute "INSERT INTO SSHistoryQ322([Date], Material, Data)" & _
"VALUES('Date()-" & rst.Fields(x).Name & "', " & rst!Material & ", " & rst.Fields(x) & ")"
Next
rst.MoveNext
Loop
End Sub
Then as long as there aren't more than 254 unique Material values, build CROSSTAB from the query or table.
TRANSFORM First(Query1.Data) AS FirstOfData
SELECT Query1.Date
FROM Query1
GROUP BY Query1.Date
PIVOT Query1.Material;
Recommend not using Date as a field name because it is a reserved word.
Related
I am using an MS Access append query to append inventory transactions to my ERP database (MYSQL).
Please advise how I would go about to modify my query to automatically insert the next sequential transaction ID (primary key) into the Inventory_transaction table, with ability to append multiple records at once.
My existing query works fine, but only when I append just one record.
I usually need to append multiple records simultaneously. Each record needs to have a unique sequential transaction ID (primary key). There would be multiple users using this app simultaneously, so I need minimal chance of duplicate a key violation, to prevent roll backs. I tried appending without using a primary key to see if my database would automatically assign a transaction ID, but unfortunately this this ERP field is not an auto-number and I cant modify the table structure...
Below are 2 queries.
This one currently works for generating a transaction ID for just one record.
SELECT Max([SYSADM_INVENTORY_TRANS].[TRANSACTION_ID])+1 AS new_inventory_transaction_ID
FROM SYSADM_INVENTORY_TRANS;
The 2nd query is the append query that contains the first query and I would much appreciate it if someone can modify the query so the user has ability to append multiple records at once with a unique transaction ID.
INSERT INTO SYSADM_INVENTORY_TRANS ( TRANSACTION_ID, WORKORDER_TYPE,
WORKORDER_BASE_ID, WORKORDER_LOT_ID, WORKORDER_SPLIT_ID, WORKORDER_SUB_ID,
OPERATION_SEQ_NO, REQ_PIECE_NO, PART_ID, TYPE, CLASS, QTY, COSTED_QTY,
TRANSACTION_DATE, WAREHOUSE_ID, LOCATION_ID, USER_ID, POSTING_CANDIDATE,
ACT_MATERIAL_COST, ACT_LABOR_COST, ACT_BURDEN_COST, ACT_SERVICE_COST,
CREATE_DATE, ADD_BURDEN, COUNT_SEQUENCE, DESCRIPTION )
SELECT T.new_inventory_transaction_ID, S.WORKORDER_TYPE, D.WORKORDER_BASE_ID,
D.WORKORDER_LOT_ID, D.WORKORDER_SPLIT_ID, D.WORKORDER_SUB_ID, D.OPERATION_SEQ_NO,
D.PIECE_NO, D.auto_issue_part_ID, S.TYPE, S.CLASS, D.[total_auto_issue Qty],
0 AS Expr6, Date() AS Expr1, D.BACKFLUSH_WHS_ID, D.BACKFLUSH_LOC_ID,
"SYSADM" AS Expr3, S.POSTING_CANDIDATE, S.ACT_MATERIAL_COST, S.ACT_LABOR_COST,
S.ACT_BURDEN_COST, S.ACT_SERVICE_COST, Date() AS Expr2, S.ADD_BURDEN,
S.COUNT_SEQUENCE, "ENTERED WITH ACCESS APP" AS Expr5
FROM tbl_static_autoissue_data AS S,
tbl_dynamic_autoissue_data AS D,
qry_transaction_ID_generator AS T;
Here are some notes that may help you towards your goal, however life would be a lot easier and a lot safer with autonumbers. This is VBA as you mention MS Access.
Function NextTranNumber(ByRef FirstTran As Long, _
ByRef LastTran As Long, Optional BlockSize = 1)
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strSQL As String
Dim lngResult As Long
Dim strCon As String
lngResult = 0 'assume fail
strCon = TestCon ''Connection to back-end
cn.Open strCon
rs.CursorType = adOpenKeyset
rs.LockType = adLockPessimistic
rs.CursorLocation = adUseServer
''Where BEInfo is a single line table that holds a transaction seed
strSQL = "SELECT ASeqNumber FROM BEInfo"
rs.Open strSQL, cn, , , adCmdText
'Note this is ADO, so no rs.Edit
FirstTran = rs!ASeqNumber + 1
rs!ASeqNumber = rs!ASeqNumber + BlockSize
rs.Update
LastTran = rs!ASeqNumber
rs.Close
Set rs = Nothing
End Function
Sub TransactionProcessing()
Dim FirstTran As Long
Dim LastTran As Long
Dim db As Database
Dim sSQL As String
Dim Block As Long
Dim rs As DAO.Recordset
Set db = CurrentDb
'Existing temporary table
sSQL = "DELETE FROM FETempTrans"
db.Execute sSQL, dbFailOnError
'The records to be added to the main table
sSQL = "INSERT INTO FETempTrans ( ID, AText ) SELECT 0 AS ID, AText FROM Table1"
db.Execute sSQL, dbFailOnError
Block = db.RecordsAffected
'Reserve a transaction block based on the temp table count
NextTranNumber FirstTran, LastTran, Block
Set rs = db.OpenRecordset("FETempTrans")
Do While Not rs.EOF
rs.Edit
rs!ID = FirstTran
rs.Update
FirstTran = FirstTran + 1
rs.MoveNext
Loop
If FirstTran - 1 = LastTran Then
'compare the temp set to the main table
'if it passes, update the main table
Else
'fail
End If
End Sub
I'm trying to show columns in a query where the value is not null in Ms Access (2010).
I have a query that now gives me this, where name, field1,... are the column headers:
Name | field1 | field2 | field 3 | field 4 | field5
mike | x | | x | x |
So now I don't want to see Field2 and Field5 in that query. I have a lot more fields then 5, and I only want to see the one with a value.
It's also fine If you can tell me a way to get the column names ( ex field1, field3,field4)
Thanks
You'll have to use a simple WHERE statement in your SQL. For example:
SELECT tbl.*, tbl.field2, tbl.field5
FROM tbl
WHERE tbl.field2 Is Not NULL AND tbl.field5 Is Not Null;
This will return all fields and all rows, where field2 and field5 are not Null.
EDIT: Since I am more familiar with vba, I would use the following approach to reach the desired output as stated in the comments.
Start by creating the query.
SELECT tbl.*
FROM tbl
WHERE tbl.ID = 12345;
Let's say you name it "qry_record". Afterwards, I would loop through the fields with a recorset, and create a new dynamic sql statement with the fields that have a value.
Dim rs As Recordset
Dim fld As Field
Dim sqlstatement As String: sqlstatement = "SELECT "
Set rs = CurrentDb.OpenRecordset("qry_record")
With rs
.MoveFirst
For Each fld In .Fields
If IsNull(fld.value) = False Then
Debug.Print fld.Name
sqlstatement = sqlstatement & "tbl." & fld.Name & ", "
End If
Next
End With
rs.Close
Set rs = Nothing
sqlstatement = sqlstatement & "FROM tbl"
DoCmd.RunSQL sqlstatement
EDIT: I have tested the code, and made a minor adjustment. Should work fine now on any table in your access database.
I have a table which has 30 different fields. I want sum of all the columns only when they have particular values. I don't want value of a field to be considered for summing when the value in it doesn't satisfy particular condition. For example, I have 5 fields id, Score1, Score2, Score3, Score4. I want sum of all these different fields only when they don't have values -8 or -9 in them. How can I do this.
In "real" SQL you would use a CASE statement, but it looks like that isn't supported in Access (except via VBA). Try using something like:
iif(score1 <> -8 and score1 <> -9, score1, 0) + iif(score2 <> -8 and score2 <> -9, score2, 0) + ....
Check out this for details on iif http://office.microsoft.com/en-us/access-help/iif-function-HA001228853.aspx
In SQL you can use a query like this,
SELECT c_id,ch_id, (IIF(Response4 <> -8 AND Response4 <> -8, Response4 , 0)) +
(IIF(Response3 <> -8 AND Response3 <> -8, Response3 , 0)) AS Score
from Teacher_Questionnaire ;
In VBA you can use the same as follows:
Dim db As Database
Dim rs As Recordset
Dim sSQL As String
Dim sSQL1 As String
sSQL = " SELECT SUM ( " & _
"(IIF(Teacher_Questionnaire.Response4 <> -8 AND Teacher_Questionnaire.Response4 <> -8, Teacher_Questionnaire.Response4 , 0)) + " & _
"(IIF(Teacher_Questionnaire.Response3 <> -8 AND Teacher_Questionnaire.Response3 <> -8, Teacher_Questionnaire.Response3 , 0)) ) AS Score" & _
"from Teacher_Questionnaire where ch_id = 99"
Set db = CurrentDb
Set rs = db.OpenRecordset(sSQL)
If rs.RecordCount > 0 Then
Me.TxtLevel1 = rs!Score
Else
Me.TxtLevel1 = "N/A"
End If
Set rs = Nothing
Set db = Nothing
End Sub
I am using an MS Access append query to append inventory transactions to my ERP database (MYSQL).
Please advise how I would go about to modify my query to automatically insert the next sequential transaction ID (primary key) into the Inventory_transaction table, with ability to append multiple records at once.
My existing query works fine, but only when I append just one record.
I usually need to append multiple records simultaneously. Each record needs to have a unique sequential transaction ID (primary key). There would be multiple users using this app simultaneously, so I need minimal chance of duplicate a key violation, to prevent roll backs. I tried appending without using a primary key to see if my database would automatically assign a transaction ID, but unfortunately this this ERP field is not an auto-number and I cant modify the table structure...
Below are 2 queries.
This one currently works for generating a transaction ID for just one record.
SELECT Max([SYSADM_INVENTORY_TRANS].[TRANSACTION_ID])+1 AS new_inventory_transaction_ID
FROM SYSADM_INVENTORY_TRANS;
The 2nd query is the append query that contains the first query and I would much appreciate it if someone can modify the query so the user has ability to append multiple records at once with a unique transaction ID.
INSERT INTO SYSADM_INVENTORY_TRANS ( TRANSACTION_ID, WORKORDER_TYPE,
WORKORDER_BASE_ID, WORKORDER_LOT_ID, WORKORDER_SPLIT_ID, WORKORDER_SUB_ID,
OPERATION_SEQ_NO, REQ_PIECE_NO, PART_ID, TYPE, CLASS, QTY, COSTED_QTY,
TRANSACTION_DATE, WAREHOUSE_ID, LOCATION_ID, USER_ID, POSTING_CANDIDATE,
ACT_MATERIAL_COST, ACT_LABOR_COST, ACT_BURDEN_COST, ACT_SERVICE_COST,
CREATE_DATE, ADD_BURDEN, COUNT_SEQUENCE, DESCRIPTION )
SELECT T.new_inventory_transaction_ID, S.WORKORDER_TYPE, D.WORKORDER_BASE_ID,
D.WORKORDER_LOT_ID, D.WORKORDER_SPLIT_ID, D.WORKORDER_SUB_ID, D.OPERATION_SEQ_NO,
D.PIECE_NO, D.auto_issue_part_ID, S.TYPE, S.CLASS, D.[total_auto_issue Qty],
0 AS Expr6, Date() AS Expr1, D.BACKFLUSH_WHS_ID, D.BACKFLUSH_LOC_ID,
"SYSADM" AS Expr3, S.POSTING_CANDIDATE, S.ACT_MATERIAL_COST, S.ACT_LABOR_COST,
S.ACT_BURDEN_COST, S.ACT_SERVICE_COST, Date() AS Expr2, S.ADD_BURDEN,
S.COUNT_SEQUENCE, "ENTERED WITH ACCESS APP" AS Expr5
FROM tbl_static_autoissue_data AS S,
tbl_dynamic_autoissue_data AS D,
qry_transaction_ID_generator AS T;
Here are some notes that may help you towards your goal, however life would be a lot easier and a lot safer with autonumbers. This is VBA as you mention MS Access.
Function NextTranNumber(ByRef FirstTran As Long, _
ByRef LastTran As Long, Optional BlockSize = 1)
Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strSQL As String
Dim lngResult As Long
Dim strCon As String
lngResult = 0 'assume fail
strCon = TestCon ''Connection to back-end
cn.Open strCon
rs.CursorType = adOpenKeyset
rs.LockType = adLockPessimistic
rs.CursorLocation = adUseServer
''Where BEInfo is a single line table that holds a transaction seed
strSQL = "SELECT ASeqNumber FROM BEInfo"
rs.Open strSQL, cn, , , adCmdText
'Note this is ADO, so no rs.Edit
FirstTran = rs!ASeqNumber + 1
rs!ASeqNumber = rs!ASeqNumber + BlockSize
rs.Update
LastTran = rs!ASeqNumber
rs.Close
Set rs = Nothing
End Function
Sub TransactionProcessing()
Dim FirstTran As Long
Dim LastTran As Long
Dim db As Database
Dim sSQL As String
Dim Block As Long
Dim rs As DAO.Recordset
Set db = CurrentDb
'Existing temporary table
sSQL = "DELETE FROM FETempTrans"
db.Execute sSQL, dbFailOnError
'The records to be added to the main table
sSQL = "INSERT INTO FETempTrans ( ID, AText ) SELECT 0 AS ID, AText FROM Table1"
db.Execute sSQL, dbFailOnError
Block = db.RecordsAffected
'Reserve a transaction block based on the temp table count
NextTranNumber FirstTran, LastTran, Block
Set rs = db.OpenRecordset("FETempTrans")
Do While Not rs.EOF
rs.Edit
rs!ID = FirstTran
rs.Update
FirstTran = FirstTran + 1
rs.MoveNext
Loop
If FirstTran - 1 = LastTran Then
'compare the temp set to the main table
'if it passes, update the main table
Else
'fail
End If
End Sub
How can i compare two MS ACCESS 2007 databases.Both databases contain same tables with same feilds ad structure.i need to compare the record values between two databases to detect any difference in record values.
ACCESS 2007 Database1
serial no. | NAME | ADDRESS
1 smith street 1
2 john street 4
3 alix street 8
ACCESS 2007 Database2
serial no.| NAME | ADDRESS
1 smith street 1
2 jhn stret 4
3 alix street 8
I need a VBA code for ms access that can detect the differece of records,just as the records at serial number two.
First thing you should do is link in one of the tables to the other database, e.g link the Database 2 table into database one (this allows both to be queried together) then you could use this simple example with concatenation to determine if all the fields strung together match based on the serial number:
SELECT T1.*, T2.*
FROM Table1 As T1, Table2 As T2
WHERE T2.[serial no.] = T1.[serial no.]
AND T2.[NAME] & T2.[ADDRESS] <> T1.[NAME] & T1.[ADDRESS]
You could also specify the columns with each of their own condition if you prefer.
NOTE: This is assuming you are only looking for differences where the serial no matches, if you also need to identify records that may appear in one table but not the other then you will need to use an "Un-matched" query, the query designer can help you with this or post back and I can update my answer.
Option Compare Database
Private Sub Command4_Click()
Dim tablename1, tablename2 As String
tablename1 = Text0.Value
tablename2 = Text2.Value
'On Error GoTo Err_cmdValidateGeneralInfo_Click
Dim F As DAO.Field
Dim rs As DAO.Recordset
Dim rs1 As DAO.Recordset
Set curDB = CurrentDb()
'If Me.DateModified = Date Then
'Adds new employees to the TT_GeneralInfo table in the FTEI_PhoneBook.mdb - which is used thru out the AP databases.
' DoCmd.OpenQuery "qryEmpData_TT_General"
strsql = "Select * from " & tablename1
Set rs = curDB.OpenRecordset(strsql)
strsql1 = "Select * from " & tablename2
DoCmd.CopyObject , "Unmatched_records", acTable, tablename1
curDB.Execute "DELETE FROM Unmatched_records"
Set rs1 = curDB.OpenRecordset(strsql1)
Do Until rs.EOF
For Each F In rs.Fields
If rs.Fields(F.Name) <> rs1.Fields(F.Name) Then
'rs.Edit
strsql = "Select * into test from " & tablename1 & " where " & F.Name & " = """ & rs.Fields(F.Name) & """"
DoCmd.RunSQL strsql
If DCount(F.Name, "test") <> 0 Then
GoTo append_unmatch
'appending unmacthed records
append_unmatch:
strsql2 = "insert into Unmatched_records Select * from test"
DoCmd.RunSQL strsql2
'if record doesnt match move to next one
GoTo Nextrecord
End If
' rs.Fields(F.Name) = rs1.Fields(F.Name)
' rs.Update
End If
Next F
Nextrecord:
rs.MoveNext
rs1.MoveNext
Loop
'To check whether tables matched or not
Dim rs2 As DAO.Recordset
strsql3 = "select * from Unmatched_records"
Set rs2 = curDB.OpenRecordset(strsql3)
For Each F In rs2.Fields
If DCount(F.Name, "Unmatched_records") <> 0 Then
MsgBox ("The two tables didnt match. Check table test for unmatching reocrds.")
Else
MsgBox ("Tables match!")
End If
Exit Sub
Next F
rs2.Close
End Sub