I want to show some selected columns as my SQL column and the rest of the column should be pivot. My output should be: Please help me any idea ?
Pivot table
ID | Employee_ID | 01-sep-2019 | 02-sep-2019 | 03-sep-2019
───┼─────────────┼─────────────┼─────────────┼────────────
1 | 1001 | P | A | P
2 | 1002 | A | P | A
3 | 1003 | A | P | P
Original table
ID | Employee_ID |STATUS | Created_Date
───┼─────────────┼───────┼─────────────
1 | 1001 | P | 01-sep-2019
2 | 1002 | A | 02-sep-2019
3 | 1003 | P | 03-sep-2019
I use 2 `GridView to show data but it's applicable for all column that I don't need. Could you please help me?
private DataTable PivotTable(DataTable origTable) {
DataTable newTable = new DataTable();
DataRow dr = null;
//Add Columns to new Table
for (int i = 0; i <= origTable.Rows.Count; i++) {
newTable.Columns.Add(new DataColumn(origTable.Columns[i].ColumnName, typeof(String)));
}
//Execute the Pivot Method
for (int cols = 0; cols < origTable.Columns.Count; cols++) {
dr = newTable.NewRow();
for (int rows = 0; rows < origTable.Rows.Count; rows++) {
if (rows < origTable.Columns.Count) {
dr[0] = origTable.Columns[cols].ColumnName; // Add the Column Name in the first Column
dr[rows + 1] = origTable.Rows[rows][cols];
}
}
newTable.Rows.Add(dr); //add the DataRow to the new Table rows collection
}
return newTable;
}
private void BindGridView() {
string strConnString = ConfigurationManager.ConnectionStrings["SQLDBConnection"].ConnectionString;
SqlConnection con = new SqlConnection(strConnString);
try {
con.Open();
string sqlStatement = "SELECT Top(5)* FROM tbl_QC_Attandence";
SqlCommand sqlCmd = new SqlCommand(sqlStatement, con);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
DataTable dt = new DataTable();
sqlDa.Fill(dt);
if (dt.Rows.Count > 0) {
//Bind the First GridView with the original data from the DataTable
grdorignal.DataSource = dt;
grdorignal.DataBind();
//Pivot the Original data from the DataTable by calling the
//method PivotTable and pass the dt as the parameter
DataTable pivotedTable = PivotTable(dt);
grdpivote.DataSource = pivotedTable;
grdpivote.DataBind();
}
} catch (System.Data.SqlClient.SqlException ex) {
string msg = "Fetch Error:";
msg += ex.Message;
throw new Exception(msg);
} finally {
con.Close();
}
}
ORIGINAL TABLE
ID Employee_ID STATUS Created_Date
1 1001 P 01-sep-2019
2 1002 A 02-sep-2019
3 1003 P 03-sep-2019
PIVOT TABLE
ID Employee_ID 01-sep-2019 02-sep-2019 03-sep-2019
1 1001 P A P
2 1002 A P A
3 1003 A P P
I have create a dynamic query which can help you, but null can be replaced with 'A' in code side, try below one
DECLARE
#columns NVARCHAR(MAX) = '',
#sql NVARCHAR(MAX) = '',
#SelectColumnNames AS NVARCHAR(MAX);
SELECT
#columns += QUOTENAME([Created_Date]) + ','
FROM
Employee
ORDER BY
[Created_Date];
SET #columns = LEFT(#columns, LEN(#columns) - 1);
Select #SelectColumnNames = ISNULL(#SelectColumnNames + ',','')
+ 'ISNULL(' + QUOTENAME([STATUS]) + ', 0) AS '
+ QUOTENAME([STATUS])
from (SELECT distinct [STATUS] from Employee) as Employees
print #SelectColumnNames
SET #sql =
N'Select * from(
select Created_Date,[STATUS],ID,Employee_ID
from Employee
)t
PIVOT(
MAX([STATUS])
FOR [Created_Date] IN ('+ #columns +')
) AS pivot_table
';
EXECUTE sp_executesql #sql;
Related
I have two data tables as shown below.
datatable1:
table1_id(PK) DriverID Vehicle
111 Ram00 VRN01
112 Shyam00 VRN02
113 Ram00 VRN03
datatable2:
table2_id(PK) DriverID exit_time
AA1 Ram00 10.10AM
AA2 Hari00 11.20PM
Combined Output
table1_id DriverID Vehicle table2_id exit_time
111 Ram00 VRN01 AA1 10.10AM
112 Shyam00 VRN02 NULL NULL
113 Ram00 VRN03 AA1 10.10AM
NULL Hari00 NULL AA2 11:20PM
DriverID is common in both table. But just merging two datatable will not give this result.
Please help to achieve this.
datatable1.Merge(datatable2);
You can use Two Data tables to combine into one Data table via Coding and Remove the Extra Column later the For loop ends,Check my code it will work.
string Qry = "select tab1.table_id,'' as DriverID,vehicle,tab1.driver_id Tab1DrvrID,exit_time from tab1 " +
"full join tab2 on tab2.driver_id=tab1.driver_id";
cmd = new SqlCommand(Qry, con);
da = new SqlDataAdapter(cmd);
dt = new DataTable();
da.Fill(dt);
//string DrvrID;
for (int i = 0; i < dt.Rows.Count; i++)
{
string Qry2 = "select tab1.table_id,'' as DriverID,vehicle,tab1.driver_id Tab1DrvrID,tab2.driver_id Tab2DrvrID,exit_time from tab1 " +
"full join tab2 on tab2.driver_id=tab1.driver_id ";
cmd = new SqlCommand(Qry2, con);
SqlDataAdapter daa = new SqlDataAdapter();
DataTable dtt = new DataTable();
daa = new SqlDataAdapter(cmd);
daa.Fill(dtt);
if (dtt.Rows.Count > 0)//
{
string s=dtt.Rows[i]["Tab1DrvrID"].ToString();
if (s=="")
{
dt.Rows[i]["DriverID"] = dtt.Rows[i]["Tab2DrvrID"].ToString();
}
else
{
dt.Rows[i]["DriverID"] = dtt.Rows[i]["Tab1DrvrID"].ToString();
}
}
else
{
}
dt.AcceptChanges();
}
dt.Columns.Remove("Tab1DrvrID");
Merge works properly if columns from two DATATABLES are matched in the same DATATYPE. If the column has a NULL value in the first row of DATATABLE the column DATATYPE will be String. So the second DATATABLE, if have value Date or any other type, will miss the match on merge . To resolve this problem you need to make the two DATATABLES columns same DATATYPE.
private DataTable MergeDataTable(DataTable dataTable1, DataTable dataTable2)
{
var dtCloned = dataTable2.Clone();
foreach (DataColumn column in dataTable2.Columns)
{
var col = dataTable1.Columns[column.ColumnName];
if (col != null && col.DataType != column.DataType )
{
dtCloned.Columns[column.ColumnName].DataType = col.DataType;
}
}
foreach (DataRow d in dataTable2.Rows)
{
dtCloned.ImportRow(d);
}
dataTable1.Merge(dtCloned);
return dataTable1;
}
My SQL query is:
GridView1.DataSource = GetData();
GridView1.DataBind();
DataTable GetData()
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["OfficeConnection"].ConnectionString))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("SELECT * FROM Consulting ", con))
{
SqlDataAdapter adpt = new SqlDataAdapter(cmd);
adpt.Fill(dt);
}
}
return dt;
}
I have a table with a few columns and what I am trying to achieve is to display the data in a GridView. At the moment the data is displayed in my GridView but I would like to replace text in the columns and then display in the gridview
So for example this is my table:
| DisplayName | $_License
+-------------+------------------------
| User 1 | TestLicense:License1 |
| User 2 | TestLicense:License2 |
So in my Gridview I would to display:
| Display Name | License Type |
+--------------+------------------------+
| User 1 | License1 |
| User 2 | License2 |
Note that theDisplay Name has a space and the $_License is changed to License Type and the row is changed from TestLicense:License1 to License1
Any help will be greatly appreciated.
Use this query:
"SELECT DisplayName 'Display Name', Replace($_License,'TestLicense:', '') 'License Type' Name FROM Consulting "
Modify your select query as per required result:
SELECT DisplayName AS 'Display Name' , RIGHT($_License, LEN($_License) - 11) AS 'License Type' FROM Consulting;
I have an Access table which looks like this:
ID | col_1 | col_2 | col_n
1 | 12345 | ... | ...
1 | null | ... | ...
1 | null | ... | ...
2 | 67891 | ... | ...
What I want to accomplish is to get all col_1 with the ID 1 if there is at least one value in col_1 with that ID. So my result would be:
ID | col_1
1 | 12345
1 | null
1 | null
The following code gets me the all the values of ID and col_1 and stores them in a DataTable results0.
public void ConnectDB(string path, string query0, string query1)
{
string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Persist Security Info=False";
try
{
using (OleDbConnection conn = new OleDbConnection(connString))
{
DataTable results0 = new DataTable();
OleDbCommand cmd = new OleDbCommand(query0, conn);
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
adapter.Fill(results0);
}
}
catch (System.InvalidOperationException inv)
{
MessageBox.Show(inv.Message);
throw;
}
}
I wanted to use LINQ for this issue, since I don't want to loop through the rows and tried a few things without success. At first I thought something like this would give me the relevant values (which it does)
int id = 1;
for (int i = 0; i < 9; i++) // iterate through IDs and increment
{
IEnumerable<String> Ids =
results0
.AsEnumerable()
.Where(row => row.Field<Int32>("ID") == id)
.Select(row => row.Field<String>("FERI"));
id+=1;
}
but I'm not sure how to rephrase it in an if-statement. Something like "If ID = 1 and at least one value in col_1 get range of rows with ID = 1"
I hope this isn't too confusing.
Any help and suggestions are appreciated!
Update: I'm still having trouble getting the relevant rows. I tried using DataRow[], selecting all the rows with ID = 1 and iterating with foreach-loops but this doesn't seem really efficient. Can anyone help?
To get the list of records with ID==1 from the Database assuming database with name "DBName", we will have:
public DBName _dbContext = new DBName ();
and then using following LINQ query we will get result:
_dbContext.TableName.Where(u => u.ID == 1).Select(u => u.col_1 ).ToList();
Real easy.
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("col_1", typeof(int));
dt.Columns["col_1"].AllowDBNull = true;
dt.Rows.Add(new object[] { 1, 12345});
dt.Rows.Add(new object[] { 1, null});
dt.Rows.Add(new object[] { 1, null});
dt.Rows.Add(new object[] { 2, 67891});
int id = 1;
DataTable dt2 = dt.AsEnumerable().Where(x => x.Field<int>("ID") == id).CopyToDataTable();
I'm trying to delete all the rows, starting from the bottom of the table using a condition, but when that conditions is met then i want it to stop updating the table and leave the rest as it was. Example, if the last entry on the table meets it, delete it, if the one after it does not meet the condition then stop there, and exite the loop.
Here's the code i got, but its deleting all the rows :
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("A atualizar dados");
bool check = true;
do
{
string connectionString = #"Data Source=.\wintouch;Initial Catalog=bbl;User ID=sa;Password=Pa$$w0rd";
string queryString = string.Empty;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
queryString = "DELETE FROM wgcdoccab
WHERE serie ='1' AND tipodoc ='FSS'
AND contribuinte ='999999990'
and datadoc = CONVERT(varchar(10),(dateadd(dd, -2, getdate())),120)"
SqlCommand command = new SqlCommand(queryString, connection);
//command.Connection.Open();
command.ExecuteNonQuery();
}
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
queryString = "SELECT * FROM wgcdoccab
WHERE serie !='1' and tipodoc !='FSS'
and contribuinte !='999999990'
and datadoc != CONVERT(varchar(10),(dateadd(dd, -1, getdate())),120) ";
using (SqlCommand command = new SqlCommand(queryString, connection))
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
check = true;
}
else
{
check = false;
MessageBox.Show("Dados Apagados com sucesso");
}
command.Connection.Close();
}
}
}
while (check);
Try something like this example:
DELETE
FROM tableName
WHERE ID >
(
SELECT MAX(ID)
FROM tableName
WHERE condition = false
)
For example, if you want to delete until a value is 4:
DELETE
FROM tableName
WHERE ID >
(
SELECT MAX(ID)
FROM tableName
WHERE tableName.Value = 4
)
If the table rows are:
|ID|Value|
| 1| 7|
| 2| 4|
Then the subselect will be 2 and no rows will be deleted. However, if the rows are:
|ID|Value|
| 1| 7|
| 2| 4|
| 3| 9|
| 4| 1|
Then the subselect will still return the ID of 2, and the last 2 rows will be deleted.
I am running a stored procedure and the result is this format
+------+--------+-----+-------+
| ID | Resign | Sum | Count |
+------+--------+-----+-------+
| 1234 | 0 | 400 | 3 |
| 1234 | 1 | 800 | 4 |
+------+--------+-----+-------+
I tried this code to reference the values returned by the query but, it seem not working the way I want it
if (conn.State != ConnectionState.Open)
conn.Open();
SqlCommand sc = new SqlCommand();
sc.CommandText = "usp_GetResignPool";
sc.CommandType = CommandType.StoredProcedure;
sc.Connection = conn;
sc.Parameters.Add(AddParam(EndDate, "#EndDate"));
sc.Parameters.Add(AddParam(am_id, "#id"));
SqlDataReader reader;
reader = sc.ExecuteReader();
while (reader.Read())
{
if reader. // lost here
}
How can I do something like this. ↓
int resigned = 0, resign_count = 0, not_resigned = 0, notresign_count =0;
if (read["Resigned"] == 1)
{
resigned = read["sum"];
resign_count = read["count"];
}
else
{
not_resigned = read["sum"];
notresign_count = read["count"];
}
It is not important that I used SQLDataReader.
Edit: Real column names
ID Resigned sum count
--------- ----------- ---------------------- -----------
It didn't work because you don't have a column in your table named "Resigned", like you have when you are working with your SqlDataReader.
EDIT: I think the root of the problem is the way you are adding parameters. AddParam() is not the method you want to be using. Therefore, your result set is probably empty.
....
SqlCommand sc = new SqlCommand();
sc.CommandText = "usp_GetResignPool";
sc.CommandType = CommandType.StoredProcedure;
sc.Connection = conn;
sc.Parameters.AddWithValue("#EndDate", EndDate);
sc.Parameters.AddWithValue("id", am_id);
SqlDataReader reader;
reader = sc.ExecuteReader();
using (reader = sc.ExecuteReader())
{
while (reader.Read())
{
if (Convert.ToInt32(read["Resign"]) == 1)
{
resigned = Convert.ToInt32(read["Sum"]);
resign_count = Convert.ToInt32(read["Count"]);
}
else
{
not_resigned = Convert.ToInt32(read["Sum"]);
notresign_count = Convert.ToInt32(read["Count"]);
}
}
}
Notice how I changed your element indicator to "Resign". This needs to match the column that is returned in your dataset. Or, you could use a column number to get this, like so:
if (Convert.ToInt32(read[1]) == 1)
{
resigned = Convert.ToInt32(read[2]);
resign_count = read[3];
}
else
{
not_resigned = Convert.ToInt32(read[2]);
notresign_count = Convert.ToInt32(read[3]);
}
Also, keep in my that in every iteration or your while loop, you'll be overwriting the variables resigned, resign_count or not_resigned and notresign_count.
Would this work?
int resign = 0;
int not_resign = 0;
int resign_count = 0;
int not_resign_count = 0;
while (reader.Read())
{
if (Convert.ToInt32(reader["Resigned"]) == 1)
{
resign = Convert.ToInt32(reader["Sum"]);
resign_count = Convert.ToInt32(reader["Count"]);
}
else
{
not_resign = Convert.ToInt32(reader["Sum"]);
not_resign_count = Convert.ToInt32(reader["Count"]);
}
}
Can you post your query from the procedure?
Are the column names really "Sum" and "Count"?
There are reserved words, maybe you should try using "AS" and give other names to these to columns in the projection.