我有一个应用程序,用户在其中输入用于查询数据库并返回匹配行的搜索词。我想找到重复的行,如下所示:
File Tool Product Time1 MeasureTime Row
319 S32 AX 11/13 1:12AM 11/13 5:02am 5
318 S32 AX 11/13 1:12AM 11/13 4:41am 5
在这些情况下,具有较高文件ID的条目可能是错误的重新测量,因此我希望能够向用户突出显示。
我有这段代码可以计数是否存在重复的行:
var duplicates = db2.AsEnumerable()
.GroupBy(r => new
{
Tool = r.Field<string>("Tool"),
Product = r.Field<string>("Product"),
Time1 = r.Field<DateTime>("Time1"),
Row = r.Field<Int32>("Row")
}).Select(g => new {
Tool = g.Key.Tool,
Product = g.Key.Product,
Time1 = g.Key.Time1,
Row = g.Key.Row,
Count = g.Count() }).ToList();
这将返回一个通用列表,我希望能够从中获取计数并将其添加回初始数据表db2中。然后,当用户选择计数大于1的行时,我可以提醒用户。我只想在用户选择较高的文件号时发出警报,因此我可能需要对排名进行排序,但是无论哪种方式,我如何才能将自己拥有的文件重新添加到原始表中?
答案 0 :(得分:0)
如上所述,您将需要创建一个新列表,因为您丢失了对原始数据的引用:
import random
import logging
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
WHITE, BLACK, YELLOW, ORANGE, RED = QtGui.QColor("white"), QtGui.QColor("black"), QtGui.QColor("yellow"), QtGui.QColor("orange"), QtGui.QColor("red")
DEFAULT_FONT = QtGui.QFont()
class QHandler(logging.Handler, QtWidgets.QTextEdit):
def __init__(self, parent=None):
QtWidgets.QTextEdit.__init__(self, parent)
logging.Handler.__init__(self)
self.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
self.setReadOnly(True)
self.emit_lock = threading.Lock()
def emit(self, record):
with self.emit_lock:
QtCore.QMetaObject.invokeMethod(self,
"append",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, self.format(record)))
QtCore.QMetaObject.invokeMethod(self,
"autoScroll",
QtCore.Qt.QueuedConnection)
def format(self, record):
if record.levelno == logging.INFO:
bgcolor = WHITE
fgcolor = BLACK
elif record.levelno == logging.WARNING:
bgcolor = YELLOW
fgcolor = BLACK
elif record.levelno == logging.ERROR:
bgcolor = ORANGE
fgcolor = BLACK
elif record.levelno == logging.CRITICAL:
bgcolor = RED
fgcolor = BLACK
else:
bgcolor = BLACK
fgcolor = WHITE
self.setTextBackgroundColor(bgcolor)
self.setTextColor(fgcolor)
self.setFont(DEFAULT_FONT)
record = logging.Handler.format(self, record)
return record
@QtCore.pyqtSlot()
def autoScroll(self):
self.verticalScrollBar().setSliderPosition(self.verticalScrollBar().maximum())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.status_handler = QHandler()
self.setCentralWidget(self.status_handler)
logging.getLogger().addHandler(self.status_handler)
self.status_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logging.getLogger().setLevel(logging.DEBUG)
timer = QtCore.QTimer(self, interval=1000, timeout=self.on_timeout)
timer.start()
def on_timeout(self):
logging.info('From Gui Thread {}'.format(QtCore.QDateTime.currentDateTime().toString()))
class Subprocess_Thread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.logger = logging.getLogger(self.__class__.__name__)
self.logger.info('Subprocess Thread Created')
def run(self):
while True:
t = random.choice(["info", "warning", "error", "critical"])
msg = "Type: {}, thread: {}".format(t, threading.currentThread())
getattr(self.logger, t)(msg)
QtCore.QThread.sleep(1)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
app.setStyle('Fusion')
w = MainWindow()
w.show()
th = Subprocess_Thread()
th.daemon = True
th.start()
sys.exit(app.exec_())
或者,如果您从代码中删除var updateList = db2.Where(r=> Tool = r.Field<string>("Tool")
&& Product = r.Field<string>("Product")
&& Time1 = r.Field<DateTime>("Time1")
&& Row = r.Field<Int32>("Row"));
foreach (var ul in updateList)
ul.Count = updateList.Count();
,则可以保留对原始数据的引用:
Select
答案 1 :(得分:0)
显然,您设计的是可以通过Tool
,Product
等值来标识度量:如果您有两项具有相同的Tool
,{{1 }}等,它们属于同一度量标准组,甚至可能是同一度量标准。
为防止我不得不一遍又一遍地说“相同的工具,产品等”,我将这些属性的集合称为Product
。因此,每当我说MeasurementId
时,我的意思是属性Tool / Product / Timel / Row
如果您使用相同的MeasurementId
进行了两次测量,则可能是重新测量。因此,每当操作员选择其他MeasurementId
具有相同测量值的测量时,您都想警告操作员,如果操作员选择了最早的测量值,可能就不会发出警告。
您的问题似乎类似于在数据库中保留某事物的多个版本。如果有人向您的数据库中添加了具有相同“ MeasurementId MeasurementId
文件. but with a different
版本”的新项。
如果操作员未选择最早的版本,则要对其进行警告。
您选择了以下解决方案:
我希望能够从中获取计数并将其添加回初始数据表db2
不要在表中添加计数,而是考虑添加“先前版本”的ID,如果没有先前版本,则添加0。
, it is as if you add a new
在添加度量之前,请检查是否已经存在类似度量:
class Measurement
{
public int Id {get; set;}
public int File {get; set;}
// measurement identification
public string Tool {get; set;}
public string Product {get; set;}
...
// you wanted to add a Count, instead add a previous version
public int PreviousMeasurementId {get; set;} // 0 if no previous measurement
}
现在,如果已经有相似的度量,则lastMeasurementVersionId是最后一个相似的度量的ID。如果没有,则该值等于0。
在将lastMeasurementVersionId分配给void AddMeasurement(Measurement measurementToAdd)
{
var lastMeasurementVersionId = dbContext.Measurements
.Where( measurement => // select with same measurementId:
measurement.Tool == measurementToAdd.Tool
&& measurement.Product == measurementToAdd.Product
&& ...)
// from the remaining versions, keep the one with the highest File:
.OrderByDescending(measurement => measurement.File)
// I'm only interested in the Id of this measurement
.Select(measurement => measurement.Id)
.FirstOrDefault();
后添加新的测量值:
PreviouseMeasurementId
如果操作员选择了 measurementToAdd.PreviousMeasurementId = lastMeasurementVersionId;
dbContext.Measurements.Add(measurementToAdd);
dbContext.SaveChanges();
}
,那么您唯一要做的就是检查Measurement
的值。如果为零,则操作员选择了第一个测量;如果不为零,则可以警告操作员此测量有多个版本。所选的可能是重新测量。
可能的改进:
PreviousMeasurementId
添加一个额外的索引。 MeasurementId
的值不会经常更改,但是使用此MeasurementId
获取所有度量的查询要快得多MeasurementId
,而要记住PreviousMeasurementId
。