Truy vấn trong SQL?

Liên hệ QC

Hoàng Nhật Phương

Thành viên gắn bó
Tham gia
5/11/15
Bài viết
1,894
Được thích
1,213
Xin chào các bạn.
OT chạy câu lệnh sau:
Mã:
SELECT
    sc.name + '.' + ta.name TableName,
    SUM(pa.rows) RowCnt
FROM
    sys.tables ta
INNER Join
    sys.partitions pa
ON
    pa.OBJECT_ID = ta.OBJECT_ID
INNER Join
    sys.Schemas sc
ON
    ta.schema_id = sc.schema_id
WHERE
    ta.is_ms_shipped = 0
AND
    pa.index_id IN (1,0)
Group BY
    sc.name,
    ta.name
Order BY
    Sum (pa.Rows)
DESC
Kết quả trả về tên bảng và số dòng của bảng và sắp xếp giảm giần theo cột số dòng trong bảng.

Mã:
SELECT
    TABLE_NAME,
COLUMN_NAME
FROM
     INFORMATION_SCHEMA.Columns
Kết quả trả về tên bảng và tên các cột trong bảng.

Xin hỏi có câu lệnh nào để trả về 3 dữ liệu: tên bảng, tên cột trong bảng, số dòng trong cột?
 
"Số dòng trong cột" là như thê nào nhỉ?
thường thì mình nói về số dòng của bảng, vì ô mà không có dữ liệu (NULL) thì vẫn là một ô.
 
Xin chào các bạn.
OT chạy câu lệnh sau:
Mã:
SELECT
    sc.name + '.' + ta.name TableName,
    SUM(pa.rows) RowCnt
FROM
    sys.tables ta
INNER Join
    sys.partitions pa
ON
    pa.OBJECT_ID = ta.OBJECT_ID
INNER Join
    sys.Schemas sc
ON
    ta.schema_id = sc.schema_id
WHERE
    ta.is_ms_shipped = 0
AND
    pa.index_id IN (1,0)
Group BY
    sc.name,
    ta.name
Order BY
    Sum (pa.Rows)
DESC
Kết quả trả về tên bảng và số dòng của bảng và sắp xếp giảm giần theo cột số dòng trong bảng.

Mã:
SELECT
    TABLE_NAME,
COLUMN_NAME
FROM
     INFORMATION_SCHEMA.Columns
Kết quả trả về tên bảng và tên các cột trong bảng.

Xin hỏi có câu lệnh nào để trả về 3 dữ liệu: tên bảng, tên cột trong bảng, số dòng trong cột?
Câu lệnh tra cứu tên các database trong SQL là:
select name from sys.databases

Câu lệnh tra cứu tên các bảng trong 1 database là:
select table_name from information_schema.tables

Câu lệnh tra cứu tên các cột trong 1 table là:
select column_name from INFORMATION_SCHEMA.COLUMNS where table_name = 'chungtu'
ở đây đang Ví dụ tên bảng là chung tu (table_name='chungtu')
 
"Số dòng trong cột" là như thê nào nhỉ?
thường thì mình nói về số dòng của bảng, vì ô mà không có dữ liệu (NULL) thì vẫn là một ô.

Xin chào anh Bình,

Đúng rồi thường là sẽ nói về số dòng của bảng bảng cột nào nhiều dòng nhất thì sẽ lấy số dòng của cột đó.
Ở đây OT muốn lấy dữ liệu của các ô có dữ liệu của các cột trong bảng như minh họa ảnh kèm bên dưới ạ.

Mục đích cũng chỉ là hỏi để xem có câu lệnh này không?
Và OT muốn sử dụng câu lệnh này để kiểm tra thông tin thôi ạ.
Mong anh và mọi người xem giúp ạ.


Untitled.jpg
 

Theo như hình của bạn, thông tin vừa lấy từ các table hệ thống vừa truy vấn số dòng NOT NULL trong từng table riêng nên tôi nghĩ là không có cách join các table để lấy thông tin trực tiếp như bạn yêu cầu mà phải dùng cách đi vòng: tạo table tạm lưu thông tin (Tên bảng, Tên Cột, Ô có dữ liệu) rồi mới cập nhật dữ liệu vào table này. Các bạn chuyên về SQL Server có cách khác thì hỗ trợ giùm nhé.

Cách tôi làm như sau: Vì bạn chủ yếu muốn thống kế nên tôi làm kiểu thủ công trực tiếp trong SQL Server nhé.

1. Tạo table tạm:

Mã:
USE NORTHWIND --Đổi tên Database của bạn.
GO
CREATE TABLE myDBInfo (
    TblName VARCHAR(30),
    ColName VARCHAR(30),
    NumRow INT
);


2. Insert dữ liệu từ INFORMATION_SCHEMA.COLUMNS vào table tạm:

Mã:
USE NORTHWIND
GO
INSERT INTO myDBInfo SELECT TABLE_NAME, COLUMN_NAME,0 FROM INFORMATION_SCHEMA.COLUMNS


3. Tạo các stored proc. (SP) để thực thi việc cập nhật dữ liệu: tạo 2 SP

- SP: UpdatemyDBInfoTbl

Mã:
USE [NORTHWIND]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[UpdatemyDBInfoTbl]
@TName nvarchar(30),
@CName nvarchar(30)
AS
BEGIN
SET NOCOUNT ON;
Declare @sql nvarchar(300);
    Set @sql='UPDATE myDBInfo SET NumRow = (SELECT count(*) FROM ' +  @TName + ' WHERE ' + @CName + ' Is Not Null) WHERE myDBInfo.TblName =''' + @TName + ''' AND myDBInfo.ColName =''' + @CName + ''''
    EXEC sp_executesql @sql
    --print @sql
END

- SP: GetNumRowNotNull

Mã:
USE [NORTHWIND]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[GetNumRowNotNull]

AS
BEGIN
declare @TName varchar(30)
Declare @CName varchar(30)
declare cur CURSOR LOCAL for
    select TblName, ColName from myDBInfo

open cur

fetch next from cur into @TName, @CName


while @@FETCH_STATUS = 0 BEGIN
--print @TName
--print  @CName
    --Chạy Store Proc. cho từng dòng
 
    exec dbo.UpdatemyDBInfoTbl @TName, @CName

    fetch next from cur into @TName, @CName

END

close cur
deallocate cur
END


==> Xong. Bây giờ chạy lệnh thực thi SP trên.

Mã:
Exec sp_executesql GetNumRowNotNull

Và xem kết quả:

Mã:
select * from mydbinfo


220786


- Trong Excel bạn dùng ADO Command để gửi lệnh yêu cầu SQL Server thực thi cái stored proc. "GetNumRowNotNull".
- Sau đó bạn dùng ADO Recordset để lấy dữ liệu từ table "myDbInfo" về Excel sheet như cách bạn đang làm.
- Một cái quan trọng để tránh lỗi cho cái SP trong SQL server là đặt tên Table, tên Field không có khoảng trắng nhé.
 
Lần chỉnh sửa cuối:
Theo như hình của bạn, thông tin vừa lấy từ các table hệ thống vừa truy vấn số dòng NOT NULL trong từng table riêng nên tôi nghĩ là không có cách join các table để lấy thông tin trực tiếp như bạn yêu cầu mà phải dùng cách đi vòng: tạo table tạm lưu thông tin (Tên bảng, Tên Cột, Ô có dữ liệu) rồi mới cập nhật dữ liệu vào table này. Các bạn chuyên về SQL Server có cách khác thì hỗ trợ giùm nhé.

Cách tôi làm như sau: Vì bạn chủ yếu muốn thống kế nên tôi làm kiểu thủ công trực tiếp trong SQL Server nhé.

1. Tạo table tạm:

Mã:
USE NORTHWIND --Đổi tên Database của bạn.
GO
CREATE TABLE myDBInfo (
    TblName VARCHAR(30),
    ColName VARCHAR(30),
    NumRow INT
);


2. Insert dữ liệu từ INFORMATION_SCHEMA.COLUMNS vào table tạm:

Mã:
USE NORTHWIND
GO
INSERT INTO myDBInfo SELECT TABLE_NAME, COLUMN_NAME,0 FROM INFORMATION_SCHEMA.COLUMNS


3. Tạo các stored proc. (SP) để thực thi việc cập nhật dữ liệu: tạo 2 SP

- SP: UpdatemyDBInfoTbl

Mã:
USE [NORTHWIND]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[UpdatemyDBInfoTbl]
@TName nvarchar(30),
@CName nvarchar(30)
AS
BEGIN
SET NOCOUNT ON;
Declare @sql nvarchar(300);
    Set @sql='UPDATE myDBInfo SET NumRow = (SELECT count(*) FROM ' +  @TName + ' WHERE ' + @CName + ' Is Not Null) WHERE myDBInfo.TblName =''' + @TName + ''' AND myDBInfo.ColName =''' + @CName + ''''
    EXEC sp_executesql @sql
    --print @sql
END

- SP: GetNumRowNotNull

Mã:
USE [NORTHWIND]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[GetNumRowNotNull]

AS
BEGIN
declare @TName varchar(30)
Declare @CName varchar(30)
declare cur CURSOR LOCAL for
    select TblName, ColName from myDBInfo

open cur

fetch next from cur into @TName, @CName


while @@FETCH_STATUS = 0 BEGIN
--print @TName
--print  @CName
    --Chạy Store Proc. cho từng dòng

    exec dbo.UpdatemyDBInfoTbl @TName, @CName

    fetch next from cur into @TName, @CName

END

close cur
deallocate cur
END


==> Xong. Bây giờ chạy lệnh thực thi SP trên.

Mã:
Exec sp_executesql GetNumRowNotNull

Và xem kết quả:

Mã:
select * from mydbinfo


View attachment 220786


- Trong Excel bạn dùng ADO Command để gửi lệnh yêu cầu SQL Server thực thi cái stored proc. "GetNumRowNotNull".
- Sau đó bạn dùng ADO Recordset để lấy dữ liệu từ table "myDbInfo" về Excel sheet như cách bạn đang làm.
- Một cái quan trọng để tránh lỗi cho cái SP trong SQL server là đặt tên Table, tên Field không có khoảng trắng nhé.

Xin chào ongke0711,
Cảm ơn anh rất nhiều OT đã hiểu cách làm ạ.
Như vậy sau lần đầu (bảng "myDbInfo" đã được thiết lập) thì mỗi lần kiểm tra phải xóa cái bảng "myDbInfo" đi và lặp lại các thao tác trên phải không ạ?
Nếu vậy có câu lệnh nào cập nhật lại thông tin vào bảng "myDbInfo"không? theo OT hiểu các lần thứ 2 trở đi chỉ cần thao tác từ bước:
Là được phải không ạ?
Nếu không phải như vậy thì phiền anh có thể viết thêm câu lệnh xóa bảng "myDbInfo" với điều kiện nếu nó đang tồn tại trong Database ạ.
OT hiện giờ chưa có điều kiện môi trường để test nên xác nhận ạ :D
 
Như vậy sau lần đầu (bảng "myDbInfo" đã được thiết lập) thì mỗi lần kiểm tra phải xóa cái bảng "myDbInfo" đi và lặp lại các thao tác trên phải không ạ?
Nếu vậy có câu lệnh nào cập nhật lại thông tin vào bảng "myDbInfo"không? theo OT hiểu các lần thứ 2 trở đi chỉ cần thao tác từ bước:

Em chạy code sau để cập nhật lại cái SP "GetNumRowNotNull".
Sau này chỉ cần chạy cái SP trên, nó sẽ xoá nội dung table myDBInfo (không xoá table), cập nhật lại tên table, column sau đó cập nhật số dòng.

Mã:
USE [NORTHWIND]
GO
/****** Object:  StoredProcedure [dbo].[GetNumRowNotNull]    Script Date: 07/08/2019 7:25:45 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetNumRowNotNull]

AS
BEGIN

DELETE FROM myDBInfo
INSERT INTO myDBInfo SELECT TABLE_NAME, COLUMN_NAME, 0 FROM INFORMATION_SCHEMA.COLUMNS

declare @TName varchar(30)
Declare @CName varchar(30)
declare cur CURSOR LOCAL for
    select TblName, ColName from myDBInfo

open cur

fetch next from cur into @TName, @CName


while @@FETCH_STATUS = 0 BEGIN
--print @TName
--print  @CName
    --Chạy Store Proc. cho từng dòng
  
    exec dbo.UpdatemyDBInfoTbl @TName, @CName

    fetch next from cur into @TName, @CName

END

close cur
deallocate cur
END
 
Xin chào các bạn.
OT chạy câu lệnh sau:
Mã:
SELECT
    sc.name + '.' + ta.name TableName,
    SUM(pa.rows) RowCnt
FROM
    sys.tables ta
INNER Join
    sys.partitions pa
ON
    pa.OBJECT_ID = ta.OBJECT_ID
INNER Join
    sys.Schemas sc
ON
    ta.schema_id = sc.schema_id
WHERE
    ta.is_ms_shipped = 0
AND
    pa.index_id IN (1,0)
Group BY
    sc.name,
    ta.name
Order BY
    Sum (pa.Rows)
DESC
Kết quả trả về tên bảng và số dòng của bảng và sắp xếp giảm giần theo cột số dòng trong bảng.

Mã:
SELECT
    TABLE_NAME,
COLUMN_NAME
FROM
     INFORMATION_SCHEMA.Columns
Kết quả trả về tên bảng và tên các cột trong bảng.

Xin hỏi có câu lệnh nào để trả về 3 dữ liệu: tên bảng, tên cột trong bảng, số dòng trong cột?
Cái này là tư duy của range, bảng trong excel-vba nên bỏ đi
Khi đã quan niệm là theo Cơ sở dữ liệu - thì đối tượng quan tâm chính nên là Data (dữ liệu) và đối tượng xử lý là table, field, recordset, ... và Relationship...
 
Theo như mình biết thì ngay cả MS SQL không thể truy vấn đơn thuần để ra kết quả như trên mà phải tìm phương án đi vòng như của ongkeo711.
 
Cái này là tư duy của range, bảng trong excel-vba nên bỏ đi
Khi đã quan niệm là theo Cơ sở dữ liệu - thì đối tượng quan tâm chính nên là Data (dữ liệu) và đối tượng xử lý là table, field, recordset, ... và Relationship...
Schema là metadata.
Xáo trộn giữa metadata và data là công việc của data manager hoặc desinger.
Đây là công việc cao cấp. Thường thì sau khi hệ thống phần mềm đưa vào hoạt động cỡ 1 năm (hay 6 tháng, tuỳ theo độ lớn) thì data designer sẽ bắt đầu lập thống kê dữ liệu để hiệu chỉnh lại metadata.
Như đã nói, làm công việc này là hàng cao cấp cho nên ông nội tôi cũng không dám xía vào. Công việc không phải chỉ viết 1 cái sp rồi đọc kết quả. Từ khoá ở đây là "hiệu chỉnh".
 
Schema là metadata.
Xáo trộn giữa metadata và data là công việc của data manager hoặc desinger.
Đây là công việc cao cấp. Thường thì sau khi hệ thống phần mềm đưa vào hoạt động cỡ 1 năm (hay 6 tháng, tuỳ theo độ lớn) thì data designer sẽ bắt đầu lập thống kê dữ liệu để hiệu chỉnh lại metadata.
Như đã nói, làm công việc này là hàng cao cấp cho nên ông nội tôi cũng không dám xía vào. Công việc không phải chỉ viết 1 cái sp rồi đọc kết quả. Từ khoá ở đây là "hiệu chỉnh".
Cao cấp mà phải giải thích nôm na mới khó và tôi cũng chịu
Nên phải nói rằng cái chính cần quan tâm thì không, lại đi quan tâm cái quá chính
 
Lần chỉnh sửa cuối:
Xin chào các bạn,
Trong SQL-DB , Oanh Thơ(OT) đang sử dụng câu lệnh sau để lấy dữ liệu từ bảng SODER:
Mã:
select CODE,CDATE,QTY from SODER
Kết quả dữ liệu xuất ra như Sheet1.
Giờ OT mong muốn lấy dữ liệu như dữ liệu trong sheet2 với điều kiện >="01/09/2019" và < "01/10/2019"
Thì câu lệnh truy vấn sẽ như thế nào ạ?
 
Xin chào các bạn,
Trong SQL-DB , Oanh Thơ(OT) đang sử dụng câu lệnh sau để lấy dữ liệu từ bảng SODER:
Mã:
select CODE,CDATE,QTY from SODER
Kết quả dữ liệu xuất ra như Sheet1.
Giờ OT mong muốn lấy dữ liệu như dữ liệu trong sheet2 với điều kiện >="01/09/2019" và < "01/10/2019"
Thì câu lệnh truy vấn sẽ như thế nào ạ?
Xin lỗi OT quên đính kèm file
 

File đính kèm

  • Select.xlsx
    308.7 KB · Đọc: 38
Xin chào các bạn,
Trong SQL-DB , Oanh Thơ(OT) đang sử dụng câu lệnh sau để lấy dữ liệu từ bảng SODER:
Mã:
select CODE,CDATE,QTY from SODER
Kết quả dữ liệu xuất ra như Sheet1.
Giờ OT mong muốn lấy dữ liệu như dữ liệu trong sheet2 với điều kiện >="01/09/2019" và < "01/10/2019"
Thì câu lệnh truy vấn sẽ như thế nào ạ?

- Dùng hàm DateSerial() nhé bạn.
- Không được dùng các từ khoá của hệ thống làm tên Fieldm tên biến. "CDate"

SELECT Code, Ngay, Qty, DateSerial(Left([Ngay],4),Mid([Ngay],5,2),Right([Ngay],2)) As NgayChuyen FROM SORDER WHERE [NgayChuyen] Between #" & txtTuNgay & "# AND #" & txtDenNgay & "#"
 
- Dùng hàm DateSerial() nhé bạn.
- Không được dùng các từ khoá của hệ thống làm tên Fieldm tên biến. "CDate"

SELECT Code, Ngay, Qty, DateSerial(Left([Ngay],4),Mid([Ngay],5,2),Right([Ngay],2)) As NgayChuyen FROM SORDER WHERE [NgayChuyen] Between #" & txtTuNgay & "# AND #" & txtDenNgay & "#"

Xin chào ongke0711
Cảm ơn anh đã quan tâm và giúp đỡ.
OT truy vấn câu lệnh sau:
Mã:
SELECT Code, CDATE, Qty, DateSerial(Left([CDATE],4),Mid([CDATE],5,2),Right([CDATE],2)) As NgayChuyen FROM SORDER  WHERE [NgayChuyen] between '2019-09-01' and '2019-10-01'

Thì báo lỗi sau:
Msg 195, Level 15, State 10, Line 1
'Mid' is not a recognized built-in function name.

Nhờ anh xem giúp ạ.
Bảng SORDER này cột của nó đặt là "CDATE" ạ
 
Oh. Em xài SQL Server 2008 à? Em thay thế hàm Mid bằng hàm SubString đi.
 
Web KT
Back
Top Bottom